Should a class know about its subclasses? Should a class do something that is specific for a given subclass for instance?
My instincts tells me that is a bad design, it seems like an anti-pattern of some sort.
Should a class know about its subclasses? Should a class do something that is specific for a given subclass for instance?
My instincts tells me that is a bad design, it seems like an anti-pattern of some sort.
The answer implied by the concept of classes is "no".
Either whatever action, data or relation you're handling is part of all subclasses - then it should be handled in the superclass without checking the actual type. Or it applies only to some subclasses - then you'd have to perform run-time type checks to do the right thing, the superclass would have to be changed whenever someone else inherits from it (or it might silently do the wrong thing), changes in the derived classes can break the unchanged superclass, etc.
In short, you get a number of bad consequences which are usually bad enough to reject such solutions out of hand. If several of your subclasses do the same thing and you want to avoid code duplication (practically always a good thing), a better solution is to introduce a mid-level class from which all those subclasses can inherit the code.
Not only should it not know, it simply can't! Usually, a class can be extended anytime, anywhere. It can be extended by classes that didn't even exist when it was written.
Some languages allow extending classes to be controlled by the superclass. In Scala, a class can be marked as sealed
, which means that it can only by extended by other classes within the same compilation unit (source file). However, unless those subclasses are also sealed
or final
, the subclasses can then be further extended by other classes.
In Scala, this is used to model closed algebraic data types, so the canonical Haskell List
type:
data List a = Nil | Cons a (List a)
can be modeled in Scala like this:
sealed trait List[+A]
case object Nil extends List[Nothing]
final case class Cons[+A] extends List[A]
And you can guarantee that only those two sub-"classes" exist because List
is sealed
and thus cannot be extended outside of the file, Cons
is final
and thus cannot be extended at all and Nil
is an object
which cannot be extended anyway.
But this is a specific use case (modeling algebraic data types via inheritance) and even in this case, the superclass doesn't actually know about its subclasses. It's more a guarantee to the user of the List
type that if he does a case discrimination of Nil
and Cons
, there won't be any other alternative popping up behind his back.
The simple answer is No.
It makes code brittle and voilates two basic principles of object oriented programming.
Yes, sometimes. For example, when there is a limited number of subclasses exist. A visitor pattern is an illustration of usefulness of this approach.
Example: an abstract syntax tree (AST) nodes of some well-defined grammar can all be inherited from a single Node
class implementing a visitor pattern to handle all node types.
If I write a component for a firm and later, after I've left, someone extends it for their own purposes should I be informed about that?
No!
Same with classes. Trust your instincts.