Whenever a new instance of a class is created (§12.5), a new variable associated with that instance is created for every instance variable declared in that class or any of its superclasses.
Ramsin Khoshaba wrote:So, if I have the following line of code: Foo o = new Baz();
Then o.play() invokes Bar.play(), because Bar.play() overrides Foo.play() and o is a Baz object.
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
If you were look again to diagram, you'd see, that play() method in Foo and Bar classes has package private access modifier. That means, that you don't override play() method in Baz class.Ramsin Khoshaba wrote:So having,
Foo o = new Baz();
o.play();
How does JVM know to invoke Bar.play?
Liutauras Vilda wrote:The code as you wrote wouldn't compile. So in order to execute play() method which is defined in Baz class, you need to cast reference variable to Baz.
Ramsin Khoshaba wrote:Oh, I forgot to use the fully qualified name of Baz, so
compiles fine and invokes the play() implementation defined in Bar.
Ramsin Khoshaba wrote:Why not?
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
Winston Gutkowski wrote:
Ramsin Khoshaba wrote:Why not?
Because your next assumption - "(Of course, if the invocation occurs inside package a.)" is WRONG.
It makes no difference where the invocation occurs; only whether the class that defines the method supposedly being "overridden" actually inherits it.
Definition (in Java) is static, invocation is done at execution time.
Winston
Liutauras Vilda wrote:play method in class Baz should have public access modifier, bu that doesn't change anything anyway.
Liutauras Vilda wrote:Because refence o is of type Foo, nevertheless it is instantiated with Baz object. So, technically play method should not be visible to reference o because Baz class does not override play method from its inheritance tree.
Ramsin Khoshaba wrote:play() in Baz does not override anything, I agree. But reference o of type Foo recognizes the play() method declared inside Foo (not that of Baz). The play() method is declared in Foo, so it is Foo's member. And Foo's play() is overriden by Bar's play() (Baz is not involved here).
Liutauras Vilda wrote:
Ramsin Khoshaba wrote:play() in Baz does not override anything, I agree. But reference o of type Foo recognizes the play() method declared inside Foo (not that of Baz). The play() method is declared in Foo, so it is Foo's member. And Foo's play() is overriden by Bar's play() (Baz is not involved here).
I am sorry, but I don't get your point. What is the question and where the confusion arise?
And how that underlined part in quote is related to those two lines you showed us earlier?
Ramsin Khoshaba wrote:
Winston Gutkowski wrote:
Because your next assumption - "(Of course, if the invocation occurs inside package a.)" is WRONG.Ramsin Khoshaba wrote:Why not?
It makes no difference where the invocation occurs; only whether the class that defines the method supposedly being "overridden" actually inherits it.
Why?
I had two questions, the second of which was about how polymorphism works in *general*, i.e. the algorithm involved and why.
I asked the second question because of the two-line example printing "In Bar".
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
No, we haven't. Problem that there are few different scenarios for few different problems discussed at the same time.Ramsin Khoshaba wrote:I think we've deviated from the main questions
Liutauras Vilda wrote:It seems we all agree, that method play is not being overridden in class Baz. That is clear, right? As Winston suggested earlier, use @Override annotation to prove that to yourself.
Liutauras Vilda wrote:1. Why the lines below (particularly line 2)
Produces an error at compile time in the case when those are placed somewhere outside class Foo and possibly outside package a.
Liutauras Vilda wrote:2. Why the same lines of code do not produce compile time error when those 2 lines appear in the main within the Foo class.
Liutauras Vilda wrote:3. And the third confusion arise, why, when those 2 lines compiles as per (2nd point), executes play method which is in Bar class, but not in Foo class.
Ramsin Khoshaba wrote:
Liutauras Vilda wrote:3. And the third confusion arise, why, when those 2 lines compiles as per (2nd point), executes play method which is in Bar class, but not in Foo class.
Somewhat confused here, because: I know that play in Bar overrides play in Foo; but how does JVM know that Bar.play should be executed when o's runtime type (that is, Baz) has no member that overrides Foo.play? I've heard that there is some sort of search for an overriding method from the runtime-type and upwards in the inheritance hierarchy, but I'm not sure.
Is there any book about object-orientation that is not-so-beginner-friendly but not as technical as JLS?
All things are lawful, but not all things are profitable.
Ramsin Khoshaba wrote:Somewhat confused here, because: I know that play in Bar overrides play in Foo; but how does JVM know that Bar.play should be executed when o's runtime type (that is, Baz) has no member that overrides Foo.play? I've heard that there is some sort of search for an overriding method from the runtime-type and upwards in the inheritance hierarchy,
No, it wouldn't. Because Baz does not override play(), as play() in Bar has package private access modifier, and Baz and Bar are in different packages.Ramya Subraamanian wrote:If you were to remove Bar's play(), code compiles and now Baz's inherited play() from Foo will be called
Ramya Subraamanian wrote:If you were to remove Bar's play(), code compiles and now Baz's inherited play() from Foo will be called
The dynamic lookup process starts from a class S, determined as follows:
If the invocation mode is interface or virtual, then S is initially the actual run-time class R of the target object. If the invocation mode is super, then S is initially the qualifying type (§13.1) of the method invocation.
The dynamic method lookup uses the following procedure to search class S, and then the superclasses and superinterfaces of class S, as necessary, for method m.
Let X be the compile-time type of the target reference of the method invocation. Then:
1. If class S contains a declaration for a method named m with the same descriptor (same number of parameters, the same parameter types, and the same return type) required by the method invocation as determined at compile time (§15.12.3), then:
If the invocation mode is super or interface, then this is the method to be invoked, and the procedure terminates. If 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.
2. Otherwise, if S has a superclass, the lookup procedure of steps 1 and 2 is performed recursively using the direct superclass of S in place of S; the method to be invoked, if any, is the result of the recursive invocation of this lookup procedure.
3. If no method is found by the previous two steps, the superinterfaces of S are searched for a suitable method.
run:
In Bar
BUILD SUCCESSFUL (total time: 0 seconds)
Ramsin Khoshaba wrote:The dynamic lookup process starts from Baz
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here
If you look at this sort of code you can see why:-The runtime type of that reference is completely unknown before the code is executed.Winston Gutkowski wrote:. . . and the compiler is ONLY concerned with declared types. . . . Winston
Winston Gutkowski wrote:What happens at execution time - which is when the method actually gets "found" - is a bit different. It still starts at the declared type (Foo), but it searches downwards for the most specific version of the method (in this case play()), based on the object's runtime type (Baz). And that search only includes methods that override Foo.play().
The invocation mode, computed as follows:
If the qualifying type of the method declaration is a class, then:
If the compile-time declaration has the static modifier, then the invocation mode is static. Otherwise, if the compile-time declaration has the private modifier, then the invocation mode is nonvirtual. Otherwise, if the part of the method invocation before the left parenthesis is of the form super . Identifier or of the form TypeName . super . Identifier, then the invocation mode is super. Otherwise, the invocation mode is virtual.
If the qualifying type of the method invocation is an interface, then the invocation mode is interface.
If 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.
Ramsin Khoshaba wrote:If you reread the section of JLS 15.12.4.4 that I posted in my previous post, then you'll see that the search is upwards (unless I've misunderstood the JLS).]
"Leadership is nature's way of removing morons from the productive flow" - Dogbert
Articles by Winston can be found here