If I have an abstract class and derived classes of that class, am I correct that, according to good and practical design practice, that the derived classes should not provide extra public methods (they should only implement abstract classes and optionally override parent methods)?
Furthermore, is it acceptable practice to have a different constructor method signature for each derived class?
Personally, I see no problem with either.
As for extra public methods on derived classes:
There is limited usefulness in this, in many cases. The extra methods will not be usable when the class has been cast or set to an reference to the base class, which severely limits usefulness of this practice. That being said, there isn't anything particularly wrong with this approach. Subclasses are meant to add specific behavior - sometimes, in a class hierarchy, there is new behavior in a subclass that isn't appropriate for the base class. If the subclass is going to be used frequently on its own, it seems perfectly reasonable for the extra behavior to be modeled in the methods.
As for constructor signatures -
I see no problem with this either. Subclasses often need more information to be put into a usable state than the abstract class. That being said, I typically make sure to implement every constructor in the base class, plus add the new parameters required for the subclass.
That being said:
Unless there is good reason, I'd avoid having a subclass constructor with fewer parameters than the base class ... why would I be able to specify something on a more generic case and not the specific case? I find that it's usually confusing when subclasses have completely different construction options than their base classes.
This is the beauty of derived classes.
While a Pen class might have a write() function, a RetractablePen class which extends Pen might also have a retractPoint() function.
When you extend a class it means -- literally -- extending the functionality of it.
It's fine in general.
What you want to avoid is using the specific in the generic. i.e.
foreach(Animal a in myFarm.Animals)
{
a.Feed();
// this is a bit grim
if( a is Horse )
{
((Horse)a).CleanStable();
}
}
So it's not the act of adding the public method but rather where you call them from.
It's perfectly acceptable to add additional public methods to your derived classes. It's also perfectly acceptable to give them different contructors. (In fact, this is quite common.)
No, it's perfectly reasonable (and sometimes very necessary by design) to add additional public methods. Consider the (completely contrived) situation of a Shape
abstract base class that has a Location
member and a Size
method. When you derive Polygon
from Shape
, for example, you may want to add a public method called GetNumberOfSides()
, for example; but you don't want to have that when you derive Circle
from Shape
.
In the same way, the derived types may have very different construction requirements; it's not really possible to know what all the requirements may be when defining the abstract base class, so feel free to have differing signatures. Just because your dervied types will be polymorphic to the abstract base class doesn't mean that that base class imposes strict limitations on how you can implement the abstractions defined in that base class; you're free to pretty much do it however you want.
If you respect the Liskov substitution principle, you can do what you want.
Of course, add a method to a derived class doesn't violate the principle at all.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With