Unique methods in subclass: can't access if superclass was the cast
Hey up,
I have an abstract class - Boid - and two subclasses - PredatorBoid and PreyBoid.
If I add a method to PreyBoid (not one that's over-riding a method from Boid: its unique to this class) something that confuses me occurs.
I can access this method if I instantiate PreyBoid thus:
PreyBoid p = new Preyboid();
But how I *want* to instantiate it is as part of an array, thus:
private Boid[] boids =new Boids[x];
for (int i=0; i<numberOfBoids*2;i+=2){
boids[i] =new PreyBoid();
boids[i+1] =new PredatorBoid();
}
But if make em this way, I can no longer access the method unique to PreyBoid.
Am I missing something? Do I have to make two separate arrays for the different kind of boid (which somewhat defeats the point?)
The alternative is to add abstract methods for every different subclass method - but given that some of them are unique to the subclasses, this seems like overkill and clutter.
It also makes no difference if the superclass is abstract or not: if I start by casting the array as a Boid array, but fill it with sub-classes, I can only access the methods that have been over-ridden from the superclass.
Any thoughts gratefully received! I have read plenty about this, but can't find an answer anywhere...>
Dan,
This is war & peace... and there is no good news.
A subtype is-a supertype... that is, it's garanteed to have all the capabilities of the super-type... but a super-type is not a sub-type, and quit probably doesn't have all the capabilities of the sub-type (or you wouldn't have bothered extending it in the first place). So java (very correctly in my view) tells you to get stuffed whenever you attempt to use a super-type as one of it's sub-types.
I think you know what the options are, and I think you know that none of them are very pretty.
You can have a collection of super-types, and whenever you retrieve an instance of the super-type you can use the [url=http://www.javapractices.com/Topic31.cjp]instanceOf[/url] operator to find out exactly what sub-type of X you've got, then (safely) typecast it back to it's real type... but that's ugly, coz you tend to end up with big blocks of "if then else" statements everywhere, which just type-check & caste... it usually works out to be more code than if you'd just not used inheritance in the first place... that and you're lecturer will (should) give you a big fat zero.
Another option is to create an Interface which describes the minimum set of common behaviours required by the sub-types... remember that a class can implement as many interfaces as is required to describe it's "various contractual obligations"... but you're still stuck with having to typecast an X back to an X to get X.xOnly();
Another option is to revert to the caveman approach, and have a collection of raw Object's... which must be typecast back to X's before you can do just about anything with them. Still yuck.
And I suppose you could always do away with inheritance completely, or just write it in ANSI-C.
I suggest that you'd be better off going back to your original design and seeing if you can abstract the methods up to a point where your various types of droids have only common methods... for instance if you've got an attack droid and a defence droid then you might have an abstract base Droid class with an "Droid.engage(Droid other)" method... instead of AttackDroid.attack() and DefenceDroid.defend() methods... so they have common signatures, and you can reference those methods via the super types.
Hope that helps some... this is major bug bear of OO design... well it is for me anyway... All that abstraction can take a simple elegant program and turn it into a Swing app faster than you can say Jack The Ripper.
Cheers. Keith.
Cheers both,
Glad to know there's no simple answer, at least! In the end I'm just going to stick abstract methods in the superclass for everything: less faffing about that way.
Even if I use ArrayList, I then have to have references for all the boids, and I'll have to use an array for that... faff-a-tee-faff-faff.
Thanks very much, don't spend yer stars all at once...