posted 21 years ago
When a class implements an interface, that is a statement about what that class is. In some cases, you need to be able to deal with classes of that certain type polymorphically even though you don't require any specific behavior of them...this is where the tagging interface comes in. It allows you to recognize a class as a member of a group when there is no behavior associated with that group that distinguishes it from other classes.
Cloneable, IMHO, was a mistake in the JDK. It is definitely NOT a case where there is no behavior associated with that interface. I would argue that the clone() method should be in that interface, and it was for purely practical reasons they went another way on this. From a pure OO theory standpoint, Cloneable is not elegant. Nor is Serializable, because I could envision a system where serializable objects implement a serialize() method that returns an array of bytes or something, so it too is tied up with some functionality that the class itself could provide.
There are situations, though, where you must use an interface to specify that something can be done to a class, but the operation cannot be performed by the class itself. In this case you could use a tagging interface to specify that this class can have this thing done to it. An example might make this easier to understand.
You're writing a system where any two objects might need to communicate, but you know you're going to have 100s of instances roaming around and you don't want each instance to hold a reference to every other instance so it can perform the communication. So you write one singleton object that keeps all the references to all the instances, and when any object needs to communicate with any other, it tells the singleton, and the singleton forwards the message to the appropriate destination object. In this case, you might want to restrict which objects can work with the singleton, so you have their classes implement a tagging interface and pass a this reference into the singleton as the source of the information. The singleton nor the destination object don't really need to call any method on the source object, you just want to ensure that only objects that meet the contract of that tagging interface can use it.
This is the interesting part about tagging interfaces. You can put any contract you want in the documentation, and by implementing that tagging interface, even though the no functionality is required of the implementing class, by implementing that interface it's still agreeing to abide by its contract which can be specified in documentation. So it's still useful.
For your particular situation, I think you might be using inheritance incorrectly. Most of the time, implementing an interface or extending a class means that you are writing a class that abides by a more restrictive contract that the interface or superclass. You have a Peon interface that it doesn't seem has any particular contract associated with it, begging the question: why have it? I'd have to learn more about your game to be able to say what the proper design would be, but this doesn't sound like it to me.
sev