Las clases derivadas de una jerarquía de clases pueden a veces intercambiarse con la clase base, un proceso denominado polimorfismo basado en la herencia. Este enfoque combina las mejores características del polimorfismo basado en la interfaz con la opción de reutilizar o reemplazar código de una clase base.
Así, esto podría ser útil en un paquete de dibujo. Por ejemplo, considere el siguiente fragmento de código, que no utiliza herencia:
Sub Draw(ByVal Shape As DrawingShape, ByVal X As Integer, _
ByVal Y As Integer, ByVal Size As Integer)
Select Case Shape.type
Case shpCircle
' Insert circle drawing code here.
Case shpLine
' Insert line drawing code here.
End Select
End Sub
Este enfoque presenta algunos problemas. Si alguien decide agregar una opción de elipse posteriormente, será necesario modificar el código fuente; puede ocurrir que los usuarios a los que va dirigido ni siquiera tengan acceso al código fuente. Un problema más sutil consiste en que para dibujar una elipse se necesita otro parámetro (las elipses tienen un diámetro principal y uno secundario) que no sería relevante para el caso de la línea. Si alguien desea agregar una polilínea (múltiples líneas conectadas), entonces se agregaría otro parámetro que no sería relevante para otros casos.
La herencia resuelve la mayoría de estos problemas. Las clases base bien diseñadas dejan la implementación de métodos específicos para las clases derivadas, de modo que se pueda incluir cualquier forma. Otros programadores pueden implementar métodos en clases derivadas con la documentación de la clase base. Otros elementos de clase (como las coordenadas x e y) se pueden integrar en la clase base porque todas las descendientes los utilizan. Por ejemplo, Draw podría ser un método MustOverride:
MustInherit Class Shape
Public X As Integer
Public Y As Integer
MustOverride Sub Draw()
End Class
Después podría agregar los elementos necesarios a esa clase para las diferentes formas. Por ejemplo, una clase Line podría necesitar únicamente un campo Length:
Class Line
Inherits Shape
Public Length As Integer
Overrides Sub Draw()
' Insert code here to implement Draw for this shape.
End Sub
End Class
Este planteamiento es útil debido a que otros programadores que no tienen acceso al código fuente pueden extender la clase base con nuevas clases derivadas según sea necesario. Por ejemplo, una clase denominada Rectangle podría derivarse de la clase Line:
Class Rectangle
Inherits Line
Public Width As Integer
Overrides Sub Draw()
' Insert code here to implement Draw for the Rectangle shape.
End Sub
End Class
En este ejemplo se muestra cómo se puede pasar de clases de propósito general a clases muy específicas mediante la implementación de detalles en cada nivel.
En este punto podría ser conveniente volver a evaluar si la clase derivada realmente representa una relación de identidad o, por el contrario, es una relación de pertenencia. Si la nueva clase de rectángulo se compone solamente de líneas, entonces la herencia no es la mejor opción. No obstante, si el nuevo rectángulo es una línea con una propiedad de ancho, entonces se mantiene la relación de identidad.