Win a copy of Classic Computer Science Problems in Swift this week in the iOS forum!
  • Post Reply Bookmark Topic Watch Topic
  • New Topic

overloaded method selection  RSS feed

 
Ranch Hand
Posts: 81
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have to classes Food and Items  Food is an abstract class that extends Items. and also has three abstract classes meat fruit  and grain  that extend it that  are extended by the concreate classes  such as apple berry  rotten meat. .  Items is an abstract class that extends Things another abstract class .  I have four methods According to the java documentation when I pass a food object to  the add or remove items methods  the removeItems or additems  methods taking  the food object  as parameter should be called  as it is more specific but I have verified through console print-outs this  is not the case  and only the methods taking  the Items objects are called  and the ones taking a Food object are  never called regardless of what I pass to them.  Why?

Staff note (Liutauras Vilda):

Fixed incorrectly applied code tags

 
author
Sheriff
Posts: 23484
138
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The compiler doesn't use the actual object type at runtime to resolve the method. The compiler, obviously, runs only at compile time, and hence, only have certain data available when resolving overloaded methods.

You also need to understand the type of reference used, for both the reference pointing to the instance of the method being called, and for the references pointing to the instances being passed to the method. You did not provide this information in your question.

Henry

 
Jesse Matty
Ranch Hand
Posts: 81
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I have tried   declaring  the food  object  instances  as



but no matter how  I declare them only the removeItems ( Items item, double amount)  and addItems (Items item, double amount) methods are ever called NOT the ones that take  a Food object.
 
Henry Wong
author
Sheriff
Posts: 23484
138
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Perhaps you can provide an SSCCE?  .... as it isn't as simple as how one reference is declared.

EDIT: BTW, I should also mention that method resolution is also effected by autoboxing and var-args.... but didn't mentioned it earlier, since I somewhat concluded / assumed that you are not using either.

Henry
 
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jesse Matty wrote: I have to classes Food and Items  Food is an abstract class that extends Items. and also has three abstract classes meat fruit  and grain  that extend it that  are extended by the concreate classes  such as apple berry  rotten meat. .  Items is an abstract class that extends Things another abstract class .  I have four methods According to the java documentation when I pass a food object to  the add or remove items methods  the removeItems or additems  methods taking  the food object  as parameter should be called  as it is more specific but I have verified through console print-outs this  is not the case  and only the methods taking  the Items objects are called  and the ones taking a Food object are  never called regardless of what I pass to them.  Why?




Here is an implementation of the hierarchy you described just as you described it. It does not compile because the invocation to removeItems () is ambiguous, as reported by the compiler. This is also what is expected.

HTH

 
Henry Wong
author
Sheriff
Posts: 23484
138
C++ Chrome Eclipse IDE Firefox Browser Java jQuery Linux VI Editor Windows
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

David Simkulette wrote:
Here is an implementation of the hierarchy you described just as you described it. It does not compile because the invocation to removeItems () is ambiguous, as reported by the compiler. This is also what is expected.



Jessy issue isn't a compiler error. It is calling a method which is not what was expected. To understand the issue, we need the OP to give us an actual example that demonstrates it.  At this point, we are only guessing on what the OP's confusion is.

Henry
 
Jesse Matty
Ranch Hand
Posts: 81
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator




My question is simple say I have   apple, water, sword or some other Item declared as a type Item how to I get the correct overloaded method to be called based on whether it is  an Item Food or Water?  Would making another subclass that extends Items for all non food and non water items do the trick?

 
Sheriff
Posts: 23496
46
Eclipse IDE Firefox Browser MySQL Database
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A common way things are designed when you have a superclass (Item) and a number of subclasses (Food, Water, Sword, etc) is to have a single method



which serves to add any Item to whatever it's being added to (Things in your example). If you wanted that method to work differently for various Item subclasses then you would commonly attempt to put that different behaviour into the subclasses, rather than having an overridden method for each subclass. After all who's to say you're not going to produce a bunch more subclasses (CreditCard, Pen, etc) in the future. Writing a bunch more substantially identical overridden methods would not be good design.

In your example the only difference between your overridden methods is that the subclasses have different descriptive text ("Food", "Water", etc). It would be easy enough, and better object-oriented design, to have an Item object tell you that description, for example via a method named getDescription() which returned the appropriate text.

 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jesse Matty wrote:



My question is simple say I have   apple, water, sword or some other Item declared as a type Item how to I get the correct overloaded method to be called based on whether it is  an Item Food or Water?  Would making another subclass that extends Items for all non food and non water items do the trick?



The Java virtual machine invokes the method of the actual type of the object, not the method of its  declared type.

Each subclass will have its overriding method invoked by the VM irrespective of the fact you've declared the objects types to all be of the super class.
 
Marshal
Posts: 58829
179
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
A different way to express it.

David Simkulette wrote: . . . The Java virtual machine invokes the method of the actual type of the object, not the method of its  declared type.  . . 

That means the left half of the method call is resolved at runtime:-
Foo.method(...);
Bar.method(...);
Baz.method(...);

If Foo Bar and Baz have a suitable relationship via inheritance, the runtime decides which version of the method to call depending on the types to the left of the dot. Overriding and polymorphism.
Foo.method(Foo f);
Foo.method(Bar b);
Foo.method(Baz b);

The compiler decides which version of the method to call depending on the declared types of the variables passed on the right of the dot. Overloading. It isn't polymorphic.
Remember that overloading cannot necessarily use the runtime type of the object:-The compiler has to bind an argument to the method call in line 30. Can it bind a bus or a car? Can it tell in advance which to bind? How can it bind anything but a Vehicle? Can you use the runtime type at all? What if somehow the runtime type of vehicle becomes MotorCycle and there isn't an overloading that takes MotorCycle?
I hope that explains that the compiler has to bind the method version taking Vehicle.
 
David Simkulette
Ranch Hand
Posts: 67
1
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Campbell Ritchie wrote:
The compiler has to bind an argument to the method call in line 30. Can it bind a bus or a car? Can it tell in advance which to bind?



Java is a statically typed language. Here's what that means in this context.

The l-hand side of a variable assignment statement is an object reference with a certain type and that type will never change.  What type is it? Its declared type and subclasses of its declared type.

The r-hand side of an assignment statement is the object, the thing in memory. It also has a type and that type will also never change. It is of whatever type contained the constructor which was used to create it.

Those are two different, statically assigned  types.

If you look at your method definitions, you can see you've declared a method whose parameter has an l-hand value of "Item and any subclass of Item". That is the type of parameter it will take and that is the type its parameter  will be within that method (unless you cast it within the method).

The runtime is not going to dynamically change which method invocation it selects based on what the reference type (l-hand) is pointing to (r-hand) at runtime. It is always going to select the method whose l-hand types match.

If no exact match is found, then it will try to match based on the hierarchy of l-hand types. So if there is no method which takes Water and Water extends an Item it will invoke the method that takes an Item and treat it like an Item (unless you cast it). Why? Because :

You've declared a method whose parameter type IS "Item and all subclasses of Item".

Other languages which are not statically typed will select methods based on the type of the object the reference variable (l-hand) is pointing to (r-hand). Java definitely doesn't do that.

That's where the power of your IDEs to help you code and catch mistakes and all static analysis tools comes from. Without it, you'd have a lot of hard debugging to do at runtime.

 
Jesse Matty
Ranch Hand
Posts: 81
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

David Simkulette wrote:

Campbell Ritchie wrote:
The compiler has to bind an argument to the method call in line 30. Can it bind a bus or a car? Can it tell in advance which to bind?




If no exact match is found, then it will try to match based on the hierarchy of l-hand types. So if there is no method which takes Water and Water extends an Item it will invoke the method that takes an Item and treat it like an Item (unless you cast it). Why? Because :





That is correct but  you cannot pass an Object declared as the parent class  to a method that requires a child class even if the right hand side is the child object with out first casting.
 
David Simkulette
Ranch Hand
Posts: 67
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

David Simkulette wrote:
If no exact match is found, then it will try to match based on the hierarchy of l-hand types. So if there is no method which takes Water and Water extends an Item it will invoke the method that takes an Item and treat it like an Item (unless you cast it). Why? Because :



Jesse Matty wrote:
[That is correct but  you cannot pass an Object declared as the parent class  to a method that requires a child class even if the right hand side is the child object with out first casting.




But that's not what I said. What I said was it will pass a subclass parameter to a parameter declared to be of type superclass.
 
Campbell Ritchie
Marshal
Posts: 58829
179
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jesse Matty wrote:. . . That is correct but  you cannot pass an Object declared as the parent class  to a method that requires a child class even if the right hand side is the child object with out first casting.

I am not sure that is the question I am trying to answer.
Even if you have a declaration likeor a method call like this
there are at least two other problems.
  • 1: Once you start introducing casting, you are on thin ice. It suggests to me there is something dubious about your inheritance hierarchy.  I am pretty sure the second code block will compile (not sure about the first), but if you get any of that code to execute you are risking an exception caused by that cast.
  • 2: You cannot expect the compiler to verify the correctness of types in line 2 of the second code block. What if that line reads
    vehicle = new Car(...);?
  • Even better, that line might read
    vehicle = otherVehicle;
    You cannot expect the compiler to follow all those types, even if they are known at all at compile time. The only sensible overloading to choose is method(Vehicle). Any other compile time binding would sacrifice type‑safety.
     
    David Simkulette
    Ranch Hand
    Posts: 67
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Right. A major Good Thing about Java is just that enforces pretty strict compile-time typing. If you find that that strict typing is interfering with your coding style, then maybe Java is not the language for you.

    I learned to program is LISP which, as far as typing is concerned, is a lot like silly putty, which is also what it felt like to program in. Talk about FUN ! It's a free for all. Anything can be anything. It's great to WRITE code in because, well, yeah, you can do that... but ... the downside comes when you have to read / maintain someone else's code, because you're dependent on the clarity of their style, since there's a paucity of compile-time information relative to a language like Java.

    When you consider that the author of the code you're now trying to understand will most likely be your past self, you see the value of a clear coding style and .... a language that has static typing.. .
     
    Campbell Ritchie
    Marshal
    Posts: 58829
    179
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Yes, LISP makes Forth look easy to understand.
     
    Jesse Matty
    Ranch Hand
    Posts: 81
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    my problem was that has been solved  is  that I thought that java would call the most specific for the given object created with the right  handed assignment   I realize now that is not  the case and that java looks at the left handed assignment  when choosing which method to call.   Knowing this I have rewritten my code and the problem has been solved.

    Thanks for the information.
     
    David Simkulette
    Ranch Hand
    Posts: 67
    1
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator
    Well that is totally aweome !!!
     
    Campbell Ritchie
    Marshal
    Posts: 58829
    179
    • Mark post as helpful
    • send pies
    • Quote
    • Report post to moderator

    Jesse Matty wrote:. . . I thought that java would call the most specific for the given object created with the right  handed assignment  . . .

    No, as you have worked out (well done ) it is the most specific type to match the left side.
     
    Consider Paul's rocket mass heater.
    • Post Reply Bookmark Topic Watch Topic
    • New Topic
    Boost this thread!