I have a super class: TriggerManager
with a subclass TimedTriggerManager
. NOTE: I’m working in java
TimedTriggerManager
only deals with TimedTrigger
s, a subclass of Trigger
. TriggerManager
references all Trigger
objects. To modify the subclass (TimedTriggerManager
) to only accept TimedTriggers
into its accessors and mutators (getters and setters) I have the following questions:
1) I have in TriggerManager
the following public void addTrigger(Trigger t)
. In TimedTriggerManager
should I just override the method to throw an error if the argument (t
) is not a TimedTrigger
. If so, What error should I throw? If not, what should I do?
2) Should I add another method getTimedTrigger
to work alongside the supper class’s getTrigger
so that I don’t have to keep type casting? (Since the latter would return a Trigger
object)
3) Is there anything else I’m forgetting, or some common practice that I’m not doing?
1
Your situation reeks of the classic Shape hierarchy where a Square inherits from Rectangle (and adds the constraint that both dimensions are the same). This is generally regarded as failing the Liskov Substitution Principle (LSP), because the added constraint makes that the base-class operations are not always appropriate for the derived class.
If the getTrigger
method is only meant for use within the hierarchy, then you could turn the inheritance between TriggerManager
and TimedTriggerManager
around (making TimedTriggerManager
the base class), as a derived class may weaken the requirements placed on method parameters but not strengthen them.
If getTrigger
is also meant for outside use, then TriggerManager
and TimedTriggerManager
can’t have an inheritance relation with each other without violating the LSP.
In that case, it might be best to make TriggerManager
and TimedTriggerManager
sibling-classes that both inherit from a AbstractTriggerManager
. The AbstractTriggerManager
provides all the common functionality, but no public methods where TriggerManager
and TimedTriggerManager
place different requirements on the parameters (such as addTrigger
).
1) Yes. Unless you have a common interface for both Trigger
and TimedTrigger
, which means the TimedTriggerManager
does not require any special functionality from TimedTrigger
, you should check the type of the received Trigger
and ensure its a TimedTrigger
.
2) It doesn’t seem a good idea to me. The base class usually should not know anything about the the derived classes. So I think casting is not a big problem here. It results in a cleaner design in my opinion.
3) Do you actually use a concrete TriggerManager
class directly? One think that you may want to consider is to use an interface instead of a base object for the specialized managers.