I’m thinking about offering a new feature to Java and I would like to ask why have it been restricted by design so far:
public abstract class BodyPart {
abstract public void followBodyPart(BodyPart part);
}
public class Head extends BodyPart{
public void followBodyPart(Body body ) { //Why is this kind of implementation not allowed?
...
}
}
public class Body extends BodyPart{
public void followBodyPart(Head head ) { //and this
...
}
public void followBodyPart(Forearm leftForearm ) { //and also this
...
}
...
}
//Arm, Forearm, etc...
Why is followBodyPart(Body body) in Head not implementing followBody in BodyPart? If it would, the advantages would be clear.
Firstly, the IDE would be able to offer within it’s autocomplete feature Body objects as parameters to followBody instead of any other BodyParts objects that Head can not follow.
Secondly, the current version of Body consists of one function and many instanceof’s, which could be eliminated.
Finally, generics can help here but not solve the problem, since this code should be ported to Java ME devices.
This question was already asked, in the not appropriate forum as I discovered here
In regards to the answers, I invite you to think different. I understand that anything implementing BodyPart should accept any BodyPart, but: what I want is to be able to say that Head would be able to accept A BodyPart to follow.
Thanks.
The question was also answered in the forum post you linked..
Namely; the interface defines the function should be able to accept anything that implements
BodyPart.By implementing the function in
Headto only accept the subclassBody, but not any other subclass; you are violating that contract (since it no longer accepts anything implementingBodyPart).Interfaces are usually used to provide to “external” code, allowing them to be sure that, whichever implementation of the interface is provided; they can for sure use the functions defined by the interface.
So if this external code gets an
BodyPart, it knows it has a functionfollowBodyPartthat can accept anything extendingBodyPartas argument. That external code will, however, never know that it gotHead(or can, after casting it after an instanceof check) and thus cannot know that the interface function will only accept aBody.By request; say that you provide the
BodyPartinterface as some kind of program API. In that case, I do not directly need to know what type ofBodyPartit is. Now say that I have two of them; received through some functions in your API, for example with the signature:public BodyPart getBody(). The method states it might be aBodyI get back; but it could as well be something else (fact is, I don’t know!).According to the
BodyPartinterface; I can callfollowBodyParton the firstBodyPart, and pass the second one in as argument. However, the actualBodyimplementation would not allow this; and there is no way for me to know that.If you really want different classes to accept different entries; you should either drop the function from
BodyPartand just implement it in the subclasses.By passing those subclasses back from the API; everyone knows what they’re talking with, and what it can do (e.g.
public Body getBody()andpublic Head getHead()). Since I then have the actual implementation classes, which have the actual implementation with a certainBodyPartto ‘follow’, it isn’t a problem.An other option would be – but stated impossible in your question – to use generics; in such case you can define an Interface stating:
And the API could pass back either the implemented
BodyPart, or anAccepts<Head>instance, for example.(Edit: as I wrote this here, I forgot to keep in mind you cannot implement the same interface more then once with different generic types; so the generic interface method would need the actual implementation to encapsulate objects that can actually handle the calls, making everything even more a mess)
Bonus edit: ofcourse you can also make
AcceptsHead,AcceptsArmas interfaces and effectively working around the generics issue :).I hope this edit clears up why it would be a weird (and bad) idea to have a generic interface (using
BodyPartas argument), but only specify specific implementations in the (possibly hidden) implementation classes.