Forums Register Login

Trouble With Inheritance

+Pie Number of slices to send: Send
I'm having difficulty grasping how everything works. Here's an example:

I have a Creature class with a single method makeNoise() that just prints "I am creature, hear me ROAR!"
I have a Slime class that extends Creature and overrides the makeNoise() method to print "I am slime, hear me SQUISH!"

I created 2 Creature objects and 1 Slime object.


Now what I assume would happen is that since all slimes ARE creatures, calling the makeNoise() method on aCopy would invoke the Slime version, but it invokes the Creature version.

So basically this means that storing a reference to a subclass in an instance of a superclass means you lose all the functionality of the subclass? Why then would you ever do this? And is there a way to store a subclass within a superclass object and still call the overridden methods of the subclass?

Hope this makes some form of sense, and thanks in advance for explaining.

~Vin
+Pie Number of slices to send: Send
 

Vince Valentin wrote:...Now what I assume would happen is that since all slimes ARE creatures, calling the makeNoise() method on aCopy would invoke the Slime version


And so it should.

but it invokes the Creature version.


Just a thought, but are those methods static by any chance?

My suggestion: post your class code, and we won't have to make guesses.

Winston
+Pie Number of slices to send: Send
 

Vince Valentin wrote:I'm having difficulty grasping how everything works. Here's an example:

I have a Creature class with a single method makeNoise() that just prints "I am creature, hear me ROAR!"
I have a Slime class that extends Creature and overrides the makeNoise() method to print "I am slime, hear me SQUISH!"

I created 2 Creature objects and 1 Slime object.




No.

That code creates 2 objects. 1 Creature object, and one Slime object (which also IS-A Creature).

The aCopy line just points another reference variable at the existing Slime object. Only the reference is copied, not the object.


Now what I assume would happen is that since all slimes ARE creatures, calling the makeNoise() method on aCopy would invoke the Slime version,



It does, if Slime's version overrides Creatures.

but it invokes the Creature version.



Then Slime didn't override that method. Perhaps you made that method static? Static methods cannot be overridden. Which class's implementation to call is decided by the type of the reference at compile time.

So basically this means that storing a reference to a subclass in an instance of a superclass means you lose all the functionality of the subclass?



Nope. Definitely not.

+Pie Number of slices to send: Send
Welcome to the Ranch
Write
@Override
before the access modifier for your Slime#makeNoise() method, and compile it again. See what happens.
+Pie Number of slices to send: Send
I see, the methods were static. Amazing how you guys knew that right off the bat. I'm sorry, I will post more code in the future.

This leads me to another conundrum. I understand static methods are methods that don't require an object to be created. So since the methods were static I could do Creature.makeNoise() and that would work. What I'm not seeing is how making it static makes the creature object, which references a slime object , use the creature version of the makeNoise() method and not the slime version. Is this just how java does it or is there something I'm missing?

Sorry, I'm just really trying to understand what's going on behind the scenes rather than just accepting that the methods can't be static if I want to store a subclass object in a superclass variable.

Thanks so much,

~Vin

Here's all my code so far:

+Pie Number of slices to send: Send
Because subclass static methods HIDE the superclass static method, not override them. So calling from an instance of a superclass object would give the superclass version, and calling from a subclass would give the subclass version... I think I understand this right. Took a few read-throughs of the Java tutorial on inheritance lol. Thank you for your help, and please feel free to correct me if I'm wrong.

~Vin
+Pie Number of slices to send: Send
 

Vince Valentin wrote: This leads me to another conundrum. I understand static methods are methods that don't require an object to be created. So since the methods were static I could do Creature.makeNoise() and that would work. What I'm not seeing is how making it static makes the creature object, which references a slime object , use the creature version of the makeNoise() method and not the slime version. Is this just how java does it or is there something I'm missing?



Any method in Java which declared as either private or static or final(or a combination of these) are hidden. What I mean by hidden is, is that they cannot be overrode by the sub-classes as the sub-classes are unaware of these methods(as they are hidden )

Now since there is no overriding possible in such methods, the compiler takes care of method binding at compile time rather than during runtime (dynamic binding, late binding). Which means the compiler fixes what method to be called at compile time.

Therefore, your call - aCopy.makeNoise(); - will be resolved at compile time. So, at compile time, aCopy is resolved to still be a reference variable of the type Creature(instead of Slime) and thats why you get the output "I am creature, hear me ROAR!".

Having said all this, I see that the code that you have posted contains static variables instead of static methods. That wont yield the behavior that you want...or what I explained above!
+Pie Number of slices to send: Send
 

Vince Valentin wrote:What I'm not seeing is how making it static makes the creature object, which references a slime object , use the creature version of the makeNoise()



It's a Creature reference, not an object.

And yes, it's part of the design of Java. When you call x.foo(), if foo() is a static method, then all that matters in determining which class's foo() will be called is the declared type of the x reference, and it's determined at compile time based on the reference type of x. If, on the other hand, foo() is non-static, then which class's version of foo() is called is decided at runtime by the class of the object that the x reference points to.

Try this:

+Pie Number of slices to send: Send
Thank you all for your help on this. I understand it a lot better now, and now I see what that dynamic binding is all about hehe.

1
+Pie Number of slices to send: Send
 

Vince Valentin wrote: . . . Amazing how you guys knew that right off the bat. . . .

We’ve had a lot more practice than you.

You should always call static members on the name of the class, which would have made the cause obvious. I think it was a mistake to allow the compiler to permit calling static members on the name of an instance, but it is too late to change that now.
+Pie Number of slices to send: Send
 

Campbell Ritchie wrote:I think it was a mistake to allow the compiler to permit calling static members on the name of an instance



++
+Pie Number of slices to send: Send
There were a lot more mistakes than that, I think.
+Pie Number of slices to send: Send
 

Jeff Verdegan wrote:++


+1 button too inconspicuous?
+Pie Number of slices to send: Send
 

Tim Moores wrote:

Jeff Verdegan wrote:++


+1 button too inconspicuous?



Old habits die hard, I guess. I'm still not used to the fact that it exists.
+Pie Number of slices to send: Send
No, Jeff was signifying the number of mistakes. +1 would have been too few
+Pie Number of slices to send: Send
Have a doubt here, its in the same lines as this post

Lets say I have a public static method in my super class. I redefine the static method in my sub class however with a private or protected access specifier. The compilation error that I get in the IDE is "Cannot reduce the visibility of the inherited method".

A static/private/final method is hidden from whose perspective? Clearly from the error it seems that the subclass can see that there is a method with the same signature in the super class although its hidden.
+Pie Number of slices to send: Send
Compiler errors sometimes don’t adhere to the strict nomenclature of the Java™ Language Specification. In fact, it is difficult to ensure a particular error message is raised in response to a particular error, maybe even impossible. So the error message you have seen may be the best the compiler can manage in the circumstances. You should also consider which IDE you are using; some IDEs have different error messages; those from Eclipse are usually better than from the Sun/Oracle compiler.

Actually, if you look here, you find that the public static members of a superclass are indeed inherited by its subclasses. The method is not hidden until you create the subclass. The only inaccurate things about that error message is that it says “override”.
+Pie Number of slices to send: Send
Yes, your explanation makes good sense. An IDE or a compiler is probably designed to show best case error messages rather than the complete language specifications. Plus, even when your code contains several errors, there usually is only 1 message shown at a time.

Thanks!
You learn how to close your eyes and tell yourself "this just isn't really happening to me." Tiny ad:
a bit of art, as a gift, the permaculture playing cards
https://gardener-gift.com


reply
reply
This thread has been viewed 1129 times.
Similar Threads
getter not returning subclass instance variable values set by setter
JQ+ question
Protected members inheritance
Polymorphism vs Casting
SCJP Interfaces
Building a Better World in your Backyard by Paul Wheaton and Shawn Klassen-Koop
More...

All times above are in ranch (not your local) time.
The current ranch time is
Mar 28, 2024 17:19:35.