class Square {
public static double width;
}
class Rectangle extends Square {
public static double height;
}
Desde el punto de vista geométrico, un cuadrado es un rectángulo pero no al revés.
Si la herencia expresa una relación ontológica, Square
hereda de Rectangle
.
Desde el punto de vista de la API tiene sentido:
- Una función que recibe
Rectangle
acepta tambiénSquare
. - Una función que recibe
Square
no acepta unRectangle
.
Desde el punto de vista de la implementación:
- El
Square
tienewidth
yheight
porque los hereda deRectangle
, pero es redundante y fuente de bugs. - No hay que escribir implementaciones distintas para calcular el área del rectángulo.
Pero desde el punto de vista de los tipos de datos el rectángulo es un sub-tipo del cuadrado.
También se puede decir que el tipo Rectangle
es "menor o igual" a Square
.
Es menor porque todos los Rectangle
son Square
porque podemos ignorar el height
,
pero no todos los Square
son Rectangle
.
Por eso también tiene sentido que Rectangle extends Square
. El extends
expresa esa relación
de "menor o igual" entre tipos.
Las consecuencias en la API serían:
- Una función que recibe
Rectangle
no puede aceptar unSquare
, pero es fácil convertir unSquare
a unRectangle
. - Una función que recibe un
Square
puede aceptar unRectangle
y usar su ancho ignorando su alto. Esto es un poco confuso.
En este ejemplo no vale la pena usar herencia. Si fueran clases separadas, evitamos el problema (2).
Las consecuencias en la implementación son:
- El square se expresa sin redundancia, eliminando la posibilidad de toda una familia de bugs.
- Hay que escribir funciones distintas para calcular el área de un
Square
y de unRectangle
, aunque también se puede tener solo la función paraRectangle
ya que es fácil convertir unSquare
a unRectangle
.