I'm studying about polmorphism and interface oriented design and I'm having problems to make my class execute the proper method according the object received, to avoid using insntanceOf or typecasting.
I made a interface which represents a collection of Envelope (a wrapper to a text), and in this interface I have this method:
Interface Envelopes{
public void add(Envelope envelope);
}
My intent is to override this method in each implementation to allow each implementation to use a particular type to access envelope data. For example, I implemented it this way in my class EnvelopesWithColor (which stores envelopes with color info):
Interface EnvelopesWithColor extends Envelope{
public void add(EnvelopeWithColor envelope) {
System.out.println("ADDING ENVELOPE WITH COLOR" + envelope.getClass());
}
@Override
public void add(Envelope envelope) {
System.out.println("ADDING ENVELOPE " + envelope.getClass());
}
}
So far, so good. To avoid coupling I want do declare a Envelopes object, and start to add envelopes to it, for example.
Envelopes envelopes = new EnvelopesWithColor();
envelopes.add(new SimpleEnvelope("some text"));
envelopes.add(new SimpleEnvelopeWithColor(new SimpleEnvelope("some text with color"));
The problem is: if I instantiate Envelope using the Interface type, it does not realize what type of object is being passed and just executes the add(Envelope envelope) even when I am providing a EnvelopeWithColor, printing the result below:
ADDING ENVELOPE class SimpleEnvelope
ADDING ENVELOPE class SimpleEnvelopeWithColor
On the other hand, if I directly instantiate my Envelopes type...
new EnvelopesWithColor().add(new SimpleEnvelope("some text"));
new EnvelopesWithColor().add(new SimpleEnvelopeWithColor(new SimpleEnvelope("some text with color"));
I have this output:
ADDING ENVELOPE class SimpleEnvelope
ADDING ENVELOPE WITH COLOR class SimpleEnvelopeWithColor
Having the implementation Envelopes type defined outputs the correct result too:
EnvelopesWithColor envelopes = new EnvelopesWithColor();
envelopes.add(new SimpleEnvelope("some text"));
envelopes.add(new SimpleEnvelopeWithColor(new SimpleEnvelope("some text with color"));
Results in:
ADDING ENVELOPE class SimpleEnvelope
ADDING ENVELOPE WITH COLOR class SimpleEnvelopeWithColor
There is some (elegant) way to discover which implementation of the Envelopes interface is being sent to my add() method (by elegant I mean not using instanceof / typecasting)? I've tryed a lot of ways with generic subtyping, generic methods, wrapper methods and did not succeed. Why the implementation is not receiving the actual objects?
instanceofis not elegant?Envelopewhich only knows ofadd(Envelope). Overloading won't work unless both methods are defined in the public interface. As for the solution, you could either use the visitor pattern or stick withinstanceofinstanceof"switch", it will need to be changed if a new class is added. The difference in behavior should be implemented in a common interface method, so a new class brings along its own "case".instanceofswitch.