Consider the following class hierarchy:
class A {
compute(int a) {
compute(a, 1);
}
compute(int a, int b) {
// do some things
}
}
class B extends A {
compute(int a, int b) {
// do some stuff
}
}
if I initialize a B object like following using a A reference:
A foo = new B();
if I call:
foo.compute(1)
then, inside this method call, it will call class A's compute(int, int) or call class B's compute(int, int) ?
Any citation's from official java documentation?
i would guess you are a C++ programmer. The behavior you're pointing do happen in C++ when you don't define the compute(int, int) function as virtual.
C++ designers are always looking for extreme performance, and so the non-virtual method calls of an object are defined at compile time, to avoid an additional reference to a function pointer in its vtable, aka the table of virtual functions that it has.
If that's the case, let me tell you that in Java, all methods are implicitly defined as virtual in C++ terms. That is: for a given object any method called is always the one belonging to the object that was constructed, not to the variable that references it.
I do not have any citation upfront but let me take a shot at explaining what will happen.
We have
A foo = new B();
Here the reference type of foo is A. The object being instantiated is of type B.
Note that this statement could get compiled only if object B satisfies the is-a relationship with A. Since B extends A, B satisfies the is-a relationship with A.
The methods that could be invoked by foo are based on the reference type. Hence, foo can only invoke methods which are declared/defined in type of A. The actual method being invoked is based on the object type. Since the object referenced by foo is of type B, the method on object B is invoked. Hence, it is B.compute(int,int) that is being invoked.
The method invoked will be B.compute(int, int), which you can easily find by trying it.
Since you asked for documentation describing why this is, I will provide it. But it's not very easy to follow.
This is described in JLS Sec 15.12.4. Run-Time Evaluation of Method Invocation.
Recall that the method invocation in question is compute(a, 1);
15.12.4.1. Compute Target Reference (If Necessary)
The method invocation is of the form MethodName, and it is non-static, so the following case applies:
Otherwise, let T be the enclosing type declaration of which the method is a member, and let n be an integer such that T is the n'th lexically enclosing type declaration of the class whose declaration immediately contains the method invocation. The target reference is the n'th lexically enclosing instance of this.
So we know our target reference. This is a long-winded way of saying that we're going to invoke the method on this.
15.12.4.2. Evaluate Arguments
This is trivial, since the arguments are ints.
15.12.4.3. Check Accessibility of Type and Method
Yeah, the type and method are accessible.
15.12.4.4. Locate Method to Invoke
The invocation mode is virtual, as described in Sec 15.12.3. Hence this applies:
If the invocation mode is interface or virtual, then S is initially the actual run-time class R of the target object.
Notice that if you were to write System.out.println(getClass()) immediately before the compute(a, 1) line, it would print out B, not A when invoked in the way shown in the question. Hence the run-time class R is B, so S is B also.
Also:
Let X be the compile-time type of the target reference of the method invocation.
X is A.
Then:
class S contains a declaration for a method named m with the same descriptor
and
the invocation mode is virtual, and the declaration in S overrides X.m (§8.4.8.1), then the method declared in S is the method to be invoked, and the procedure terminates.
So, the method declared in B is invoked.
This is pretty heavy reading, and, quite honestly, you don't need to know it in this much detail. This is the first time I've actually bothered to pick through that bit of the spec.
The simple rule to remember is: if the method is overridden in a subclass, that's the one that gets invoked.
Related
I have the code for a general case:
public class A {
public String show(A obj) {
return ("A and A");
}
}
public class B extends A {
public String show(B obj) {
return ("B and B");
}
public String show(A obj) {
return ("B and A");
}
}
public class C extends B {
}
public class Test {
public static void main(String[] args) {
A a = new B();
B b = new B();
C c = new C();
System.out.println("1--" + a.show(b));
System.out.println("2--" + a.show(c));
}
}
The results are:
1--B and A
2--B and A
I know there is a priority chain from high to low in Java:
this.show(O), super.show(O), this.show((super)O), super.show((super)O)
My understanding is below:
In this code:
A a = new B()
An upcast happens. A is a parent class reference and B is a child parent class reference. When the code is compiled and run, the child parent class reference determines how the method is chosen. In this case, show(A) in class B is chosen.
There is also a requirement that polymorphism has to meet:
The method that is chosen should be included in the parent class definition.
Could someone give a more detailed explanation on the result shown?
In order to get why you get the result B and A twice, you need to know that there are 2 parts to this: compilation and runtime.
Compilation
When encountering the statement a.show(b), the compiler takes these basic steps:
Look at the object that the method is called on (a) and get its declared type. This type is A.
In class A and all of its super types, make a list of all methods that are named show. The compiler will find only show(A). It does not look at any methods in B or C.
From the list of found methods, choose the one that best matches the parameter (b) if any. show(A) will accept b, so this method is chosen.
The same thing will happen for the second call where you pass c. The first two steps are the same, and the third step will again find show(A) since there is only one, and it also matches the parameter c. So, for both of your calls, the rest of the process is the same.
Once the compiler has figured out what method it needs, it will create a byte-code instruction invokevirtual, and put the resolved method show(A) as the one it should call (as shown in Eclipse by opening the .class):
invokevirtual org.example.A.show(org.example.A) : java.lang.String [35]
Runtime
The runtime, when it eventually gets to the invokevirtual needs to do a few steps also.
Get the object on which the method is called (which is already on the stack by then), which is a.
Look at the actual runtime type of this object. Since a = new B(), this type is B.
Look in B and try to find the method show(A). This method is found since B overrides it. If this had not been the case, it would look in the super classes (A and Object) until such a method is found. It is important to note that it only considers show(A) methods, so eg. show(B) from B is never considered.
The runtime will now call method show(A) from B, giving the String B and A as result.
More detail about this is given in the spec for invokevirtual:
If the resolved method is not signature polymorphic (§2.9), then the invokevirtual instruction proceeds as follows.
Let C be the class of objectref. The actual method to be invoked is selected by the following lookup procedure:
If C contains a declaration for an instance method m that overrides (§5.4.5) the resolved method, then m is the method to be invoked, and the lookup procedure terminates.
Otherwise, if C has a superclass, this same lookup procedure is performed recursively using the direct superclass of C; the method to be invoked is the result of the recursive invocation of this lookup procedure.
Otherwise, an AbstractMethodError is raised.
For your example, the objectref is a, its class is B and the resolved method is the one from the invokevirtual (show(A) from A)
tl:dr - Compile-time determines what method to call, runtime determines where to call it from.
In your example A a = new B(), a is a polymorphic reference - a reference that can point different object from the class hierarchy (in this case it is a reference to object of type B but could also be used as a reference to object of class A, which is topmost in the object hierarchy).
As for specific behaviour you are asking about:
Why is B printed in the output?
Which specific show(B obj) method will be invoked through the reference variable depends on the reference to the object it holds at a certain point in time. That is: if it holds reference to object of class B, a method from that class will be called (that is your case) but if it would point to an object of class A, a reference of that object would be called. That explains why B is printed in the output.
hierarchy).
Why is and A printed in the output?
Method in a subclass with the same name but different signature is called method overloading. It uses static binding, which means that the appropriate method will be bound at compile-time. The compiler has no clue about the runtime type of your objects.
So show(A obj) of class A will be bound in that case. However, when the method will be actually called in runtime, its implementation from class B will be invoked (show(A obj) from class B) and that is why you see B and A and not A and A in the output.
Reference for invokevirutal (an JVM instruction called when virtual methods are executed):
If the resolved method is not signature polymorphic (§2.9), then the
invokevirtual instruction proceeds as follows.
Let C be the class of objectref. The actual method to be invoked is
selected by the following lookup procedure:
If C contains a declaration for an instance method m that overrides
(§5.4.5) the resolved method, then m is the method to be invoked, and
the lookup procedure terminates.
Otherwise, if C has a superclass, this same lookup procedure is
performed recursively using the direct superclass of C; the method to
be invoked is the result of the recursive invocation of this lookup
procedure.
Otherwise, an AbstractMethodError is raised.
For the a.show(c), the same rules apply as for B because C doesn't have any methods overloaded and it is directly inheriting from B.
EDIT:
Step by step explanation of why a.show(c) prints B and A:
Compiler recognizes object a to be objectref to object of class A (compile-time)
Because a is of type A, method A::show(A obj) is bound.
When the code is actually executed (i.e. show() method is invoked on object a), runtime recognizes that reference a polymorphically points to object of type B (that's because of A a = new B()) (runtime)
Because C extends B, runtime treats a.show(c) as it would treat b.show(c) (or b.show(b)), so B::show(A obj) is used in this case but in place of obj an object of type B is used. That's why "B and A" is being printed.
I think your question relate to another topic - Distinguishing between an Object
and a Reference. From Certified Professional SE 8 Programmer II:
In Java, all objects are accessed by reference, so as a developer you never have direct access
to the memory of the object itself. Conceptually, though, you should consider the object
as the entity that exists in memory, allocated by the Java runtime environment. Regardless
of the type of the reference that you have for the object in memory, the object itself
doesn’t change. For example, since all objects inherit java.lang.Object, they can all be
reassigned to java.lang.Object, as shown in the following example:
Lemur lemur = new Lemur();
Object lemurAsObject = lemur;
Even though the Lemur object has been assigned a reference with a different type,
the object itself has not changed and still exists as a Lemur object in memory. What
has changed, then, is our ability to access methods within the Lemur class with the
lemurAsObject reference. Without an explicit cast back to Lemur, as you’ll see in the next
section, we no longer have access to the Lemur properties of the object.
We can summarize this principle with the following two rules:
The type of the object determines which properties exist within the object in memory.
The type of the reference to the object determines which methods and variables are
accessible to the Java program.
Your reference type is A and A has only one method show(A obj) which has been overridden in B and printing B and A, that is why you are getting B and A printed always.
Suppose I have class A
public class A
{
public void method()
{
//do stuff
}
}
Also another class B
public class B extends A
{
public void method()
{
//do other stuff
}
}
Now I have the following statements:
A a = new B();
a.method();
Is this an example of run time polymorphism? If yes, then is no binding is done for the reference a at compile time?
The compiler will tell you that this can't work, because there's no relationship between A and B that will allow you to write A a = new B();
B either has to extend A or both have to implement a common interface with void method() in it.
You could have answered this very quickly by trying it with the compiler. Be an experimentalist - it's faster than forums.
UPDATE:
It works, now that B extends A. The binding that you care about, dynamic binding, is done at runtime. The static compile time type for the variable "a" is class A; at runtime it is dynamically bound to a reference of type B. Yes, I would consider this to be an example of polymorphism.
I was waiting to put my answer to another post, into a more correctly classified problem. Your question fits the concept, I've tried to explain in detail. but, since I don't know how link answers, I'll just copy/paste the complete script here .... Kindly go through it, you'll understand everything that there is to understand about your problem, you've asked
let's say compiler has to resolve a call like this : *
A a = new AA(); // Assume AA to be some subclass of class A
a->someFunc(); // and we're invoking a method "someFunc()' on a
*.
Now, compiler will go over following steps methodically.
1.) Firstly, compiler knows the declared type of variable a, so it will check whether the declared type of object a (lets call this, class A for time being), have a method with the name someFunc() and that it must be public. This method could either be declared in class A, or it could be a derived method from one of the base class(es) of class A, but it doesn't matter to compiler and it just checks for it's existence with it's access specifier being public.
Needless to say any error in this step will invite a compiler error.
2.) Secondly, once the method is validated to be a part of the class A, compiler has to resolve the call to the correct method, since many methods could be there with same name (thanks to function overloading). This process of resolving correct method is called overloading resolution. Compiler achieves this by matching the signatures of the called method with all the overloaded methods that are part of the class. So, of all the someFunc() s only the correct someFunc() (matching the signatures with called method) will be found and considered further.
3.) Now comes the difficult part, It may very well happen that someFunc() may have been overridden in one of the subclasses of the class A (lets call this class AA and needless to say it is some subclass of A), and that variable a (declared to be of type A) may actually be referring to an object of class AA, (this is permissible in C++ to enable polymorphism). Now, if the someFunc() method is declared to be of type virtual, in base class (i.e. Class A) and someFunc() has been overriden by subclass(es) of A (either in AA or classes between A and AA), the correct version of someFunc() have to be found out by the compiler.
Now, imagine you're the compiler and you have this task of finding whether the class AA has this method. Obviously, class AA will have this method since, it is a subclass of A and public access of A in class A has already been validated in Step 1 by the compiler !!! . But Alternatively, as mentioned in previous paragraph, someFunc() may be overriden by class AA (or any other class between A and AA), which is what compiler needs to catch. Therefore, you (since, your'e playing the compiler) could do a systematic check to find the bottom-most (lowest in the inheritance tree) overridden method someFunc() starting from class A and ending at class AA. In this search, you'll look for same method signatures as was validated in overloading resolution. This method will be the method which will be invoked.
Now, you may be wondering, "What the heck", is this search done everytime ? ... Well, Not really. The compiler knows the overhead of finding this everytime, and as such, maintains a data-structure called Virtual Table for every class type. Think of virtual table, as mapping from method signatures (which are publicly accessible) to the function pointers. This virtual table is made by compiler during compilation process and is maintained in-memory during program execution. In our example, class A and class AA will both have their own virtual tables. And when compiler has to be find someFunc() in class AA (since actual object pointed by variable a is of type AA), it will simply find the function pointer through the virtual table of Class AA. This is as simple has hashing into the table and is a constant time operation.
Regards
AViD
The code example you've given isn't legal, so I guess the answer is that it's not a kind of polymorphism.
You can't assign a class to a variable of an unrelated type like that. I'm guessing that you might be intending for B to derive from A?
Is this an example of run time polymorphism?
As of the edit: yes that would be runtime polymorphism, since which method is actually executed depends on what is assigned to a.
Edit:
If method() would be static, then calling a.method() would always result in the version of A being called. However, you'd then just write A.method() and if you don't do that any decent IDE would warn you about that (because it might be misleading to call a static method on an instance).
End Edit.
Compile time polymorphism would be the overloading mechanism, i.e. the compiler decides whether to use someMethod(Number) or someMethod(Integer) depending on what it knows about the parameter that is passed (if you pass a Double or just a Number it would be the first one, if you pass an Integer it would be the second).
If yes, then is no binding is done for the reference a at compile time?
What do you mean exactly? Note that the type of a will be A so you can assign everything that extends A at runtime. The compiler will just complain if the assigned value is not an A (you might trick the compiler with a cast, but this is just evil and if this breaks your program, you have been warned ;) )
It should be
public class B extends A {
public void method()
{
//do other stuff
} }
If it were compiling, it would be the B::method() that would be called. (only if you changed your code to make the B class inherit the A class).
In this case your use your object like it was only an A, but if some methods are overidden in B, then these methods are called, instead of A's methods.
I've studied that in case of instance methods, at run time the jvm uses the actual class of instance and in case of class methods the compiler will only look at the declared type of a reference variable not the actual class..
I studied this concept instance method hiding..
And in my proram I've used interface reference variable to store the object of the class and try to access the instance method of the class using this but it raise an error..
My program is as follows:
interface A
{
void show();
}
class B implements A
{
public void show()
{
System.out.println("Interface Method");
}
void info()
{
System.out.println("IN Info");
}
}
class interDemo
{
public static void main(String args[])
{
A a;
B b=new B();
a=b;
a.show();
a.info();
}
}
Please help me to understand the conept...
The compiler is telling you that the type A does not have a method called info defined. This is true: the compiler doesn't know that at runtime, the type of a will actually be B, which does have the info method. It would be unsafe to allow the a.info() call to actually be compiled and emitted into bytecodes, there's nothing to say that a will always be of type B.
This is known as static typing. In Java and other static-typed languages, you need to "cast" a variable in order to force the compiler to treat it as another type. In this case, you can write ((B) a).info().
sjr is correct. Here's another way to look at it:
You're specifying that a A can only show. That means when you have a A reference variable, that's all you can do.
That means any class that is willing to show can implement that interface. Clients that need an object to show can use an A without knowing or caring whether that the underlying class has other methods. This is a key aspect of the abstraction provided by object-oriented programming.
You might probably want to see this lecture on YouTube. It covers you problem and I hope it will help you.
In short: static type of a is A. After assigning b to a, dynamic type of a is B. So at this point, static type a is A and dynamic type of a is B. Compiler does not follow dynamic types, it only checks static types. So it will not let do anything other then static type will allow.
So in your example if you are using reference of static type A, you can only call methods from class A.
super concept without confusion
=====================================
2 rules to know from where a method will execute(when super type reference is used to call methods)
NOTE:check "object creation"/"reference assignment" statement for applying rule
1 RULE: 1st check the method to be called.If static/overloaded/single--then it becomes static polymorphism/static(compiler looks for reference type)---hence always execute from reference type
2 RULE: check method to be called --if overridden--then it becomes dynamic polymorphism(jvm looks for object type)---hence always executed from object type(i.e right to new keyword)
for example:
super s=new child();
s.play();
here 2 cases:
1st: check play() is what i.e static(static/overloaded/single method) or dynamic(overridden)
2nd: if static it will execute from super i.e reference type leads to compile time polymorphism
if dynamic it will execute from child i.e object type leads to dynamic polymorphism
class A
{
int i=10;
void show()
{
System.out.println("class A");
}
}
class B extends A
{
int i=5;
public void show()
{
System.out.println("class B");
}
}
class M
{
public static void main(String s[])
{
A a=new B();
a.show();
System.out.println(a.i);
}
}
OUTPUT= class B
10
If class A method is overridden by class B method then why not the variable 'i'?
Because variables are not virtual, only methods are.
It is not overwritten, but hidden. In your output you specifically requested the value of a.i, not ((B)a).i.
This is a "feature" of the implementation. In memory, this looks like so:
a:
pointer to class A
int i
b:
pointer to class B
int i (from A)
int i (from B)
When you access i in an instance of B, Java needs to know which variable you mean. It must allocate both since methods from class A will want to access their own field i while methods from B will want their own i (since you chose to create a new field i in B instead of making A.i visible in B). This means there are two i and the standard visibility rules apply: Whichever is closer will win.
Now you say A a=new B(); and that's a bit tricky because it tells Java "treat the result from the right hand side as if it were an instance of A".
When you call a method, Java follows the pointer to the class (first thing in the object in memory). There, it finds a list of methods. Methods overwrite each other, so when it looks for the method show(), it will find the one defined in B. This makes method access fast: You can simply merge all visible methods in the (internal) method list of class B and each call will mean a single access to that list. You don't need to search all classes upwards for a match.
Field access is similar. Java doesn't like searching. So when you say B b = new B();, b.i is obviously from B. But you said A a = new B() telling Java that you prefer to treat the new instance as something of type A. Java, lazy as it is, looks into A, finds a field i, checks that you can see that field and doesn't even bother to look at the real type of a anymore (because that would a) be slow and b) would effectively prevent you from accessing both i fields by casting).
So in the end, this is because Java optimizes the field and method lookup.
Why no field overrides in Java though?
Well, because instance field lookups in Java happen at compile time: Java simply gives you the value of the field at a given offset in object's memory (based on the type information at hand during compilation: in this case a is declared to be of type A).
void foo() {
A a = new B();
int val = a.i; // compiler uses type A to compute the field offset
}
One may ask "Why didn't compiler use type B since it knows that a is in fact an instance of B? Isn't it obvious from the assignment just above?". Of course, in the case above, it's relatively obvious and compiler may try to be smarter and figure it out.
But that's compiler design "rat hole", what if a "trickier" piece of code is encountered, like so:
void foo(A a) {
int val = a.i;
}
If compiler were "smarter", it would become its job to look at all invocations of foo() and see what real type was used, which is an impossible job since compiler can not predict what other crazy things may be passed to foo() by unknown or yet unwritten callers.
It's a design decision by the developers of Java, and is documented in the Java Language Specification.
A method with the same method signature as a method in its parent class overrides the method in its parent class.
A variable with the same name as a variable in its parent class hides the parent's variable.
The difference is that hidden values can be accessed by casting the variable to its parent type, while overridden methods will always execute the child class's method.
As others have noted, in C++ and C#, to get the same override behavior as Java, the methods need to be declared virtual.
a is an instance of A. You call the constructor B(). But it is still a A class.
That is why i equals 10;
The override from the method will be succeded.
Note a class starts not with
public class A()
but with;
public class A { ... }
Tip: You can use setters and getters to make sure of what data-members you use.
Or: You simply can set the values at the constructor instead of the class declaration.
Because by default the variables are private. You must declare it as "protected", then will be properly inherited.
I have something unclear concerning casting reference variable in Java.
I have two classes A and B. A is the super class of B.
If I have the two objects, and then the print statement:
A a = new A(); //superclass
B b = new B(); //subclass
System.out.println ((A)b);
then what exactly is happening when the println method is executed?
I know that because B is a subclass of A, I am allowed to make the following cast:
A a2 = (A)b;
I also know that when println takes a reference variable as argument, then the toString() method of the class, which has created the object-argument, is invoked (implicitly). This is so, because the method println() is looking for an argument of type String, and the toString() method represent the object as a string. And even if we don't write toString(), the method is invoked - implicitly. So, the following two statements are equivalent:
System.out.println (b);
System.out.println (b.toString());
So, my question is: what is the implicit action taken when we have
System.out.println ((A)b);
?
I suppose that the type of the reference variable b is automatically changed from B to A. The variable should still be pointing to the same object - the one created with
B b = new B();
but just the type of b would be now changed. Is this correct?
Another question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
Thanks a lot.
Regards
The cast has no impact in this case.
The System.out.println(XXX) takes parameters of different types (multiple overloaded versions) but in this case you would get the version that takes Object. Since every object in Java supports toString(), toString is invoked on the actual argument, no matter what it is.
Now, since all methods in Java are dispatched dynamically, the version that runs is the version that corresponds to the dynamic type. Casting an object of B to A only changes the static (declared) type of the expression. The dynamic type (what's really in there) is still a B. Therefore, the version in B gets invoked.
There are many declarations of println(...) in the PrintStream class (which is the type of System.out).
Two of them are:
void println(String x)
void println(Object x)
When you call println((A)b) the compiler chooses to call println(Object) because A is not String (or any of the other types that println supports). When you call println(b.toString()), the compiler chooses println(String) because you are passing a String.
In your case, casting b to A has no effect since println() doesn't have a declaration for either A or B types. But the cast will still occur (because you asked for it), or maybe it won't because the compiler optimises it away as it knows it is redundant and it can't fail and has no effect.
It is not idiomatic to write:
A a2 = (A)b;
as this is redundant since B is a subclass of A. It may be that the compiler will optimise away the cast (which is a run-time operation to check whether an object is of a particular type, never to change it's type).
Once an object of type B is constructed, it's type never changes. It is always a B:
class B extends/implements A {...}
B b = new B(); // construct a B
A a = b; // assign a B to an A variable, it's superclass
A a = (A) b // as above including check to see that b is an A (redundant, may be optimised away).
B b = a; // Syntax error, won't compile
B b = (B) a // Will check whether a is of type B then assign to variable b
In the last case, since B is a subclass of A, it may be that a holds an instance of B and the cast will succeed. Or it may be that a holds an instance of some other class that extends/implements/is A and isn't a B and you'll get a ClassCastException.
So since an object of type B always retains it's identity (it's "B"-ness) then any (instance-) methods called on that object will always call B's implementation regardless of whether the variable through which you access the object was declared as A or B.
Remember, you can only call methods that are declared in the class that the variable is defined as.
So for example, if B declares a method b_only() then the compiler won't allow you to write a.b_only(); you could write ((B)a).b_only() though.
Since Java methods all have dynamic dispatch, which function gets called doesn't depend on the static type of the reference. Therefore, the results will be the same with or without the cast. [The results could be different if you were downcasting - the casting version could throw an exception]
Is this correct?
Sort of. The result of the casting expression would be of the A type. The type of the 'b' variable will always remain of type B.
Another question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
The instance methods of the underlying object will be called. Example:
class Foo {
public static void main(String[] args) {
B b = new B();
assert "B".equals(((A) b).m());
}
}
class A {
String m() { return "A"; }
}
class B extends A {
String m() { return "B"; }
}
Always think of your object as the type it's instantiated as (B in your case). If it's upcast to A think of it as--hmm--think of it as B putting on A clothes. It may look like an A, and you may not be able to do any of the nice B things you want to do, but inside the clothes it's still a B--the clothes don't change the underlying object at all.
So the summary would be--you can only call the methods in A, but when you call it, it goes straight through and executes it as it would if it was a B.
I think when we use reference variable in java and by using this variable we can assign a object of any class type. most of the cases we create a reference variable of Interface and abstract class because we can't create the object of interface and abstract class so assign the object of class in reference variable of Interface or abstract class.
Ex-
Interface X {
public abstract void xx();
public abstract void yy();
}
Class XXX implements X {
...........
}
Class XY extends XXX {
X xy = new XXX();
}
here xy is a reference of Interface X and assign the object of Class XXX in the reference of Interface.
so according to my point of view by using reference variable we can also use interface to participate in Object creation.
The casting, as has been mentioned, is irrelevant in this case due to overridden methods being dynamically bound. Since the toString is present in all objects it meets this condition and thus the object type and method to call are determined at runtime.
Please note though, this is NOT the case with all methods since only overridden methods are dynamically bound. Overloaded methods are statically bound. Many of the answers here mention that java methods are always dynamically bound, which is incorrect.
See this question for a more detailed explanation.
question: even though I have changed the type of b to the type of the superclass, are the overriden methods in the subclass going to be called, and not those of the superclass?
in this case the method of subclass b is called ; to convincingly understand why; you may relate to the following real world scenario
consider a parent class Father exhibiting a behaviour(method): height
defined as
the father is tall ;height = 6'2"
Son is a child class inheriting the height behavior from Father ;as a result he is also tall; height being 6' clearly overriding the behaviour
whenever your subclass Son calls the behavior height on his name he displays the overridden behavior i.e his own height 6' .