What's weird about this to me, is that hello() is defined in Character, which is the base class of Player. Character implements Alive, not Player. What is the purpose of doing it this way? The reason I ask, is because I stumbled on this when learning about the newer associative array class HashMap, it was saying to initialize a new instance to write: Map m = new HashMap(). HashMap implements Map.
23 Jul, 2010, David Haley wrote in the 2nd comment:
Votes: 0
What you have here is Player being a subclass of Character, which implements the Alive interface. Classes 'extend' other classes, but 'implement' interfaces; it's just a vocabulary thing.
Character provides one overriding of the 'hello' method. (Well, more properly, Character provides the first implementation: hence the term "implements".) Player overrides it again.
You cannot call 'hello' on object 'a' because the compiler sees it as type 'Alive', not as type Character/Player, so as far as the compiler knows it does not have the method 'hello' (but it does have the method 'breathe'). It doesn't matter that what 'a' actually points to understands 'hello' – the compiler doesn't know that and so forbids it.
As somebody used to dynamic typing etc. from Ruby et al. this must seem somewhat strange to you. :tongue:
23 Jul, 2010, JohnnyStarr wrote in the 3rd comment:
Votes: 0
I guess it's not so strange, I'm just not sure what the benefit would be? It seems that if you wanted an object that was type interface, and you wanted that interface's implementation to be class then why not just initialize that class?
I can see maybe if a class implemented several interfaces, and you didn't need / want the additional methods. Say class Man implements: Alive, Mammal, Sentient, Mortal
And say, for whatever reason you wanted an object of type Sentient : Man, then sure, that would make more sense.
23 Jul, 2010, David Haley wrote in the 4th comment:
Votes: 0
Well, look at it this way… you can have a function that knows it manipulates a Map. For example, it might print out all key-value pairs in that map. Now, it really doesn't care if the map is implemented with a hash table, a binary tree, or a straight list of key-value pairs. All it cares about is that the map respects the map interface.
If you wrote your function by taking HashMap or TreeMap, you would have to write one version of the function per implementation. But that would be dumb because the functions would look exactly the same.
Now, when you instantiate the map, Map m = new HashMap(); the right-hand side obviously needs to have a concrete class. Does 'm' itself need to be declared as a Map or a HashMap? Well, that depends on whether you are going to use the "hashedness". If all you care about is that it's a map – that happens to be implemented using a hash table – I would keep it as type Map so that your intention is clear. In other words, you are making the explicit statement: "I am only caring about this thing as a Map; I happen to implement it as a HashMap for <performance, phase of the moon, mood> reasons but you don't need to care about that."
The distinction is much clearer and more obviously useful when you are setting parameters for inputs to functions (i.e., writing APIs) than when declaring the variables.
What's weird about this to me, is that hello() is defined in Character, which is the base class of Player.
Character implements Alive, not Player.
What is the purpose of doing it this way? The reason I ask, is because I stumbled on this when learning about
the newer associative array class HashMap, it was saying to initialize a new instance to write: Map m = new HashMap().
HashMap implements Map.