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.
Software Engineering Stack Exchange is a question and answer site for professionals, academics, and students working within the systems development life cycle. It only takes a minute to sign up.Sign up to join this community
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
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
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
sealed and thus cannot be extended outside of the file,
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
Cons, there won't be any other alternative popping up behind his back.
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.