• Post Reply Bookmark Topic Watch Topic
  • New Topic

Trouble With Inheritance  RSS feed

 
Vince Valentin
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Winston Gutkowski
Bartender
Posts: 10575
66
Eclipse IDE Hibernate Ubuntu
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.

 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Welcome to the Ranch
Write
@Override
before the access modifier for your Slime#makeNoise() method, and compile it again. See what happens.
 
Vince Valentin
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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:

 
Vince Valentin
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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
 
Praveen Kumar M K
Ranch Hand
Posts: 256
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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!
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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:

 
Vince Valentin
Greenhorn
Posts: 19
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.

 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Campbell Ritchie wrote:I think it was a mistake to allow the compiler to permit calling static members on the name of an instance


++
 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
There were a lot more mistakes than that, I think.
 
Tim Moores
Saloon Keeper
Posts: 4036
94
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Jeff Verdegan wrote:++

+1 button too inconspicuous?
 
Jeff Verdegan
Bartender
Posts: 6109
6
Android IntelliJ IDE Java
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
No, Jeff was signifying the number of mistakes. +1 would have been too few
 
Praveen Kumar M K
Ranch Hand
Posts: 256
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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.
 
Campbell Ritchie
Marshal
Posts: 56599
172
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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”.
 
Praveen Kumar M K
Ranch Hand
Posts: 256
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
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!
 
It is sorta covered in the JavaRanch Style Guide.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!