inheritance and polymorphism conflict - java

if a Fruit class is superClass and Apple and Orange are subclasses of Fruit,
and GoldenDelicious and Macintosh are sub classes of Apple.
Assume that the following declaration is given:
Fruit fruit = new GoldenDelicious();
Orange orange = new Orange();
Answer this question with explain
Suppose the method makeAppleCider is defined in the Apple class. Can
fruit invoke this method? Can orange invoke this method???
My answer is : Can
fruit invoke this method? No beacuse there aren't explicit cast , must do explicit cast of
fruit instance to enable invoke the method defined in Apple class. dose this answer is true ????

This dives into the static and dynamic types of a variable.
Fruit fruit;
This line declares a variable fruit with static type Fruit. This type will never change (it's static after all) and is what you will usually be using.
fruit = new GoldenDelicious();
This line is one that assigns a value that is a GoldenDelicious to that variable. The dynamic type of the variable does change to reflect this change. After all, the variable actually contains a GoldenDelicious now. The dynamic type is something you usually won't be working with, but it is what is used when you use the (evil) instanceof (and it makes sure that overwritten function are called in the right place).
Now, you want to do this:
fruit.makeAppleCider();
This will not work. Of fruit, we basically only know the static type, and the static type Fruit knows nothing of that method. (However, behind the scenes, if GoldenDelicious and Macintosh implement the function in different ways, the dynamic type will make sure the right version is called.)
As you mentioned in your answer, explicit casts could be used to change the static type of what you are working with, and as such you could make it work that way. It is better not to do that, though, as casts should be avoided and aren't "proper OOP".
In conclusion, yes, your answer was correct.
(Yes, my description is a bit technical. I hope you'll forgive me for that...)

A Fruit has no "knowledge" of the makeAppleCider method. makeAppleCider is defined in a subclass and is not a member of Fruit. A class only has access to the methods it or one of its parents defines. Given a class of a certain type, you have to trace back up the class hierarchy to see what methods you can access. You can think of the type of your variable as the starting place for the walk back up the class hierarchy.
If there is a method you want all of your classes to have access to, put it in the root of the hierarchy. Obviously, the logic of using the method should make sense or people who use your code will be confused.

The other option, of course, is to use an "interface" -- a sort of poor-man's multiple inheritance (but far easier to understand and implement than full-out multiple inheritance).
You could, eg, have an interface sorta like (not syntax checked):
public interface CiderFruit {
public void makeCider();
}
Then Apple could implement the interface:
public class Apple extends Fruit implements CiderFruit {
....
public void makeCider() {
doStuff();
}
....
}
If you then had a Quince class it could implement the same interface and one could take either an Apple or a Quince, cast it to CiderFruit (if unsure whether it's Apple or Quince), and invoke makeCider(). (One could also invoke directly with a reference typed as Apple or Quince.)

Related

Overriding, redeclaring, hiding and redefining of methods in classes, interfaces and classes implementing interfaces [duplicate]

This question already has answers here:
Can I override and overload static methods in Java?
(19 answers)
Closed 5 months ago.
Would it be correct to say that static methods in a class extended with a class, in an interface extended with an interface and in an interface implemented by a class can only be redeclared in the extending/implementing part (hiding the original method in the class extending class case), and any other method can only be overridden there? And is redefining the same as overriding?
If not, can someone please explain these concepts with a flowchart (I've looked at other explanations and they don't give me the overview I'm looking for)?
Would it be correct to say that static methods in a class extended
No. static methods fundamentally are un-inheritable, and un-overridable. Or rather, conceptually it just doesn't apply.
Saying: "This static method is an override" is a bit like stating: "This smells blue" - it's not clear what that would even mean.
overriding is relevant essentially only for the notion of dynamic dispatch. Dynamic dispatch is this idea:
class Dog {
void bark() { System.out.println("Woof"); }
}
class Bulldog extends Dog {
void bark() { System.out.println("Grrrr"); }
}
Dog d = new Bulldog();
d.bark(); // prints "Grrrr"
That's dynamic dispatch at work. d is a variable. Like all non-primitives in java, it is a reference. Meaning, values stored in this variable are the reference - a pointer. An address in an addressbook that lets you get to a house, not the house itself. d's type is Dog. Its value is a reference to an actual instance of some object (and java guarantees that whatever the actual type it is an instance of, that type is Dog or a subtype of Dog). That reference gets you an instance of Bulldog. So, when invoking bark() here, what happens?
Dynamic dispatch: Java finds the most specific implementation of this method, and calls that. So that prints Grrrr, and not Woof.
However, when talking about static methods, the entire concept doesn't apply. Dynamic dispatch occurs because there is a discrepancy between the type of the reference (which is Dog here, that's the type of variable d) and the type of the thing the reference is pointing at (which is Bulldog). Overriding as a concept exists because these 2 types may not be the same.
When invoking static methods, this doesn't come up. You always write SomeType.someStaticMethod(), so what would dynamic dispatch even be?
SIDENOTE: You can legally invoke static methods using an expression. This is legal:
List.of("a", "b"); // this is how you normally do it
List<Integer> list = new ArrayList<Integer>();
list.of("a", "b"); // this compiles and works
But make no mistake - the compiler treats it the same and cares only about the type of list, not about the object the variable is pointing at. In fact, list = null; list.of("a", "b"); works fine, no NullPointerException, proving the point that list doesn't get dereferenced when you do this. All style guides strongly recommend not doing this, for good reason.
SIDENOTE 2: Unfortunately java lets you declare a static method as final which is weird: final means: Cannot be overridden, and we just figured out that 'override' conceptually doesn't make sense for static methods. It's just what it is - it's a design error in the original java spec and java does not like making changes that break existing code unless there is an incredibly good reason to do so, and whilst this spec brainfart is annoying, it doesn't hurt much. Just don't declare your static methods final. It even adds a rule (subtypes cannot declare a static method with the same signature) which is even more bizarre. Again, disregard that - java spec error that doesn't get fixed because not worth the headache.
And is redefining the same as overriding?
Yes. 2 words for the same thing. The correct term is 'override' - both the java lang spec uses this term, and the vast majority of the community does. If I was an editor of whatever tutorial, blogpost, documentation, or presentation you got this 'redefine' term from, I'd edit it. Unless the author was specifically talking about this:
class Parent {
static void foo() {}
}
class Child extends Parent {
static void foo() {}
}
In which case 'override' is the wrong term to use (given that static methods and override are orthogonal concepts), though I wouldn't use 'redefine' either. You're just defining a method named foo in one class, and also defining a method named foo in another. The fact that one is a child of the other is irrelevant; both have a foo method now. The foo method in child does not override or redefine anything; there's no such thing in static world.
with a flowchart
A flowchart requires some sort of flow to chart. Hence the name. No such thing here.

Why not override instead of using abstract class?

This might be a simple question for many but has confused me. I am picking an example from Kathy Sierra that shows the utility of Abstract Classes but I am unable to understand the overall importance of abstract classes.
Example
We have an abstract class Car with abstract methods - power() & topSpeed(). These methods are implemented in sub classes BMW, Volkswagen and Audi.
My question is - why do we need to have the abstract class Car in the first place to customize methods for each car type? Why not have these two methods in any one of these car subtypes, say BMW and then other two - Volkswagen and Audi - can simply override these methods?
By making a method abstract, it means that people have to implement it. You require people to do so and it is impossible for people to forget to do so, as it will fail to compile if they do.
The #override annotation exists for a very similar reason, by marking a method as #override you get an error if (for example) you typed the method name wrong and aren't actually overriding something.
In many ways the abstract class is half way between an interface and a normal class - it defines what you need to do to use it in the same way an interface does, but it also handles some of the implementation for you.
Classes can only extend one other class. They can implement any number of interfaces.
For example you might have MotorVehicle inherited by Car, Motorbike and Train - but then you might have a Steerable interface implemented by Car, Motorbike and Pedalbike.
To answer the question in the comments:
If there is an Interface "I" having method m() which is implemented by class "A" and another class "B" wants to access the method m(), what is the need of interface here. Can we simply not implement that method in class A?
You can - but if on the other hand class B wants to access the method m() in both a class A and class C (where A and C don't inherit from each other or a common class containing m()) then the way to do that is to specify a common interface I and class B uses the interface type, I, not the types A and C at all.
Also remember that interfaces can be used between packages and libraries. For example Listener and Strategy patterns make heavy use of interfaces. When the Java developers wrote JButton (for example) the ActionLstener is specified as an Interface to provide maximum flexibility to people using JButtons in the future.
Why not have these two methods in any one of these car subtypes, say BMW and then other two - Volkswagen and Audi - can simply override these methods?
Wouldn't that require Volkswagen and Audi to inherit from BMW? That wouldn't be correct, since those aren't BMWs.
The abstract base class and its abstract methods form a kind of contract which inheriting objects must implement. There's no such thing as a concrete Car that isn't a more specific type. But all concrete types share commonalities. The abstract Car enforces those commonalities, allowing specific types to be treated as generic instances of Car when needed.
For example, if you have code which needs a Car on which it will invoke the Drive() method, that code doesn't care what kind of Car it gets. It will Drive() any Car. So it accepts an abstract type so that anything which implements that type can be used:
UseACar(Car car)
{
car.Drive();
}
// elsewhere
BMW myCar = new BMW();
UseACar(myCar);
Without this enforcement of the contract, a statically-typed and compiled language would have no way of guaranteeing that .Drive() exists on the object. You'd need to create a UseAX() method for every possible kind of car, each accepting a different type. Using polymorphism like this allows you to create a single, more generic method which works on any instance of the abstract type.
So that you can write code that deals with Cars without knowing what kind of car it is:
public void PrintTopSpeed(Car car)
{
System.out.println("This car's top speed is " + car.topSpeed());
}
If the Car class didn't define topSpeed(), this code wouldn't compile. You'd have to have a different version of this print function for each of your BMW, Volkswagen, Audi, etc. derived classes. This is perhaps the most basic concept in object-oriented programming, so you really need to master it. Base classes allow objects to share common behavior, and allow code to be written to use that behavior without any knowledge of what specific type of object it's dealing with.
Polymorphism is the answer. If you don't have methods power() and topSpeed() in the abstract class you can't do things like this :
List<Car> cars;
cars.add(new Porshe());
cars.add(new Ford());
for(Car car : cars){
System.out.println(car.topSpeed());
}
You would have to handle lot of thing your self if you have only custom methods in your subclasses.
This is called abstraction. Methods in abstract class are considered as protocol so that car makers should not violate.
abstraction is great when the original programmer/architect want's to allow customized behavior to some base class and ensure that the consuming programmer implements the required methods.

Inherited field in derived class - both solutions appear lame

I have some class X with the field A in it. It is a final field, initialized in constructor. Now I have a derived class Y where this field must always be an instance of B, a class that is derived from A. The problem, the class Y needs to call a number specific methods that are only available on the class B but not on its ancestor, A.
I see several solutions:
Reuse the field of the type A, inherited from X, and inside the class Y, cast A to B. This makes my code full of nasty type casts.
Add another field of the type B. Now there are no typecasts but we have two fields of slightly different type that must always hold the same value - also does not feel good.
Add all methods that B provides also to A, throw NotImplementedException. This adds some strange methods that knowingly make no sense in that class.
Which is the most right way to deal with this field? Or maybe some other, better exists? I do not think this is very language specific but must be doable in Java I am using.
The X type should probably be a generic type:
public class X<T extends A> {
protected T a;
public X(T a) {
this.a = a;
}
}
public clas Y extends X<B> {
public Y(B b) {
super(b);
}
public void foo() {
// here, this.a is of type B, without any type cast.
}
}
The only sane solution I can think of is a variation of #1: add to class Y a getter method that returns the field cast to the type B, and access the field only through this getter. That will only require one cast, and as a beneficial side effect it will also document which parts of the code require that the field be actually a B.
Solution #1 is the most correct way, in my opinion. If you know that an object is of a specific class, there's nothing wrong with casting it to that class. It'd be wrong if you were making assumptions while doing this, but this is not an assumption, according to what you're saying. Maybe make a getter method that simply casts the underlying field to the correct type and be done with it? That way, you'll only have to cast once (per subclass).
Solution #2 will cause elusive runtime errors if the fields somehow cease being properly up-to-date with each other. This seriously sounds like the worst solution.
Solution #3 still feels like bad software design. If a method exists and it's not in an abstract class and you are not in a prototyping phase, then that method should be implemented. Otherwise, you're probably just planting unnecessary traps for the user (of the class) by giving it a misleading interface.

How to find out the declared type of an identifier in Java?

I have a simple class Apple extends from another simple class Fruit.
At run-time, I could use
Fruit fruit = new Apple();
fruit.getClass();
to get the actual type of fruit object, which is Apple.class.
I could also use fruit instanceof Apple, and fruit instanceof Fruit to verify if this fruit object is an instance of Apple or Fruit. Both of these 2 expressions return true, which is normal.
But is there a way to determine precisely the declared type of fruit identifier? Which in this case is Fruit.
You're actually asking a question about the variable declaration of fruit rather than the actual runtime type of the object (which is an Apple in this case).
I think this is in general a bad idea: you just declared the variable and told the compiler that it is a Fruit, so why do you need to now need to find this out?
Just to confuse matters even more, it's worth noting that you can also have multiple variables with different declared types referencing the same object (which is still an Apple):
Fruit fruit = new Apple(); // fruit declared as Fruit, but refers to an Apple
Object thing = fruit; // thing declared as Object, refers to the same Apple
If you really want to find out the declared type, then you have a few options:
Make fruit an instance variable, and query the declared type using reflection.
Do some processing of the source code to find the variable declaration
Do some processing of the compiled bytecode to find the declaration type (although there is a possibility that an aggressive compiler might even optimise the compile time declaration away altogether, e.g. after realising that fruit can only ever be an Apple in this code)
I think all of these are pretty ugly, so my general advice would be "don't do it".
The Fruit object doesn't have a declared type. It's the variable fruit that has its type. Since the only thing you can pass around is a reference to the Fruit object, I don't think your request makes much sense. The best you could get is if you had a specific instance variable where your object is stored. You could then reflect on that field and get its declared type with Field.getType().
No, there isn't: at least not using reflection. Reflection can give you information about an object at runtime, as well as fields, methods and classes, but not local variables. If fruit was a field, you could do something like the following:
FruitBasket.class.getDeclaredField("fruit").getType();

Why in java enum is declared as Enum<E extends Enum<E>> [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
java Enum definition
Better formulated question, that is not considered a duplicate:
What would be different in Java if Enum declaration didn't have the recursive part
if language designers were to use simply Enum<E extends Enum> how would that affect the language?
The only difference now would be that someone coud write
A extends Enum<B>
but since it is not allowed in java to extend enums that would be still illegal.
I was also thinking about someone supplying jvm a bytecode that defines smth as extending an enum - but generics can't affect that as they all are erased.
So what is the whole point of such declaration?
Thank you!
Edit
for simplicity let's look at an example:
interface MyComparable<T> {
int myCompare(T o);
}
class MyEnum<E extends MyEnum> implements MyComparable<E> {
public int myCompare(E o) { return -1; }
}
class FirstEnum extends MyEnum<FirstEnum> {}
class SecondEnum extends MyEnum<SecondEnum> {}
what's wrong with this class structure? What can be done that "MyEnum<E extends MyEnum<E>>" would restrict?
This is a common question, and understandably so. Have a look at this part of the generics FAQ for the answer (and actually, read as much of the whole document as you feel comfortable with, it's rather well done and informative).
The short answer is that it forces the class to be parameterized on itself; this is required for superclasses to define methods, using the generic parameter, that work transparently ("natively", if you will) with their subclasses.
Edit: As a (non-)example for instance, consider the clone() method on Object. Currently, it's defined to return a value of type Object. Thanks to covariant return types, specific subclasses can (and often do) define that they return a more specific class, but this cannot be enforced and hence cannot be inferred for an arbitrary class.
Now, if Object were defined like Enum, i.e. Object<T extends Object<T>> then you'd have to define all classes as something like public class MyFoo<MyFoo>. Consequently, clone() could be declared to return a type of T and you can ensure at compile time that the returned value is always exactly the same class as the object itself (not even subclasses would match the parameters).
Now in this case, Object isn't parameterized like this because it would be extremely annoying to have this baggage on all classes when 99% of them aren't going to utilise it at all. But for some class hierarchies it can be very useful - I've used a similar technique myself before with types of abstract, recursive expression parsers with several implementations. This construct made it possible to write code that was "obvious" without having to cast everywhere, or copy-and-paste just to change concrete class definitions.
Edit 2 (To actually answer your question!):
If Enum was defined as Enum<E extends Enum>, then as you rightly say, someone could define a class as A extends Enum<B>. This defeats the point of the generic construct, which is to ensure that the generic parameter is always the exact type of the class in question. Giving a concrete example, Enum declares its compareTo method as
public final int compareTo(E o)
In this case, since you defined A to extend Enum<B>, instances of A could only be compared against instances of B (whatever B is), which is almost certainly not very useful. With the additional construct, you know that any class that extends Enum is comparable only against itself. And hence you can provide method implementations in the superclass that remain useful, and specific, in all subclasses.
(Without this recursive generics trick, the only other option would be to define compareTo as public final int compareTo(Enum o). This is not really the same thing, as then one could compare a java.math.RoundingMode against a java.lang.Thread.State without the compiler complaining, which again isn't very useful.)
OK, let's get away from Enum itself as we appear to be getting hung up on it. Instead, here is an abstract class:
public abstract class Manipulator<T extends Manipulator<T>>
{
/**
* This method actually does the work, whatever that is
*/
public abstract void manipulate(DomainObject o);
/**
* This creates a child that can be used for divide and conquer-y stuff
*/
public T createChild()
{
// Some really useful implementation here based on
// state contained in this class
}
}
We are going to have several concrete implementations of this - SaveToDatabaseManipulator, SpellCheckingManipulator, whatever. Additionally we also want to let people define their own, as this is a super-useful class. ;-)
Now - you will notice that we're using the recursive generic definition, and then returning T from the createChild method. This means that:
1) We know and the compiler knows that if I call:
SpellCheckingManipulator obj = ...; // We have a reference somehow
return obj.createChild();
then the returned value is definitely a SpellCheckingManipulator, even though it's using the definition from the superclass. The recursive generics here allow the compiler to know what is obvious to us, so you don't have to keep casting the return values (like you often have to do with clone(), for example).
2) Notice that I didn't declare the method final, since perhaps some specific subclasses will want to override it with a more suitable version for themselves. The generics definition means that regardless of who create a new class or how it is defined, we can still assert that the return from e.g. BrandNewSloppilyCodedManipulator.createChild() will still be an instance of BrandNewSloppilyCodedManipulator. If a careless developer tries to define it to return just Manipulator, the compiler won't let them. And if they try to define the class as BrandNewSloppilyCodedManipulator<SpellCheckingManipulator>, it won't let them either.
Basically, the conclusion is that this trick is useful when you want to provide some functionality in a superclass that somehow gets more specific in subclasses. By declaring the superclass like this, you are locking down the generic parameter for any subclasses to be the subclass itself. This is why you can write a generic compareTo or createChild method in the superclass and prevent it from becoming overly vague when you're dealing with specific subclasses.

Categories

Resources