[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Herencia del rectángulo



 A pesar de que el concepto de herencia (en terminología de la programación 
orientada a objetos) es bastante fácil de asimilar, podemos encontrarnos 
ejemplos paradójicos, como el que ilustra el libro de Robert Martin [1].

 El ejemplo en cuestión trata de modelar los conceptos Figura, Rectángulo y 
Cuadrado. Intuitivamente, los conceptos se relacionarían de una forma similar 
a ésta (imagino que se sólo se mostrará correctamente si usáis un tipo de 
letra "fijo", es decir, de tamaño independiente del carácter):

  +--------+
  | Figura |
  +--------+
      ^
     / \
    +---+
      |
      |
+------------+
| Rectángulo |
+------------+
      ^
     / \
    +---+
      |
      |
 +----------+
 | Cuadrado |
 +----------+

 Es decir, un Cuadrado no deja de ser un caso particular de Rectángulo, y 
ambos son Figuras.
 Sin embargo, Cuadrado es un Rectángulo, y a la vez no lo es, ya que que el 
concepto de Rectángulo mezcla dos definiciones: 
 Cuadrilátero cuyos lados: 
  -forman ángulos rectos,
  -tienen longitud arbitraria (2 a 2)

 Un cuadrado satisface la primera condición, pero no la segunda. Por ese 
motivo, si usáramos el modelo anterior, incurriríamos en incongruencias tales 
como métodos válidos en la clase padre Rectángulo, pero no válidos en 
Cuadrado, p.ej.: "redimensiona(base, altura)".

 La única opción es, por tanto, un refinamiento en el modelo:

         +--------+
         | Figura |
         +--------+
              ^
             / \
            +---+
              |
              |
    +------------------+
    |   Cuadrilátero   |
    +------------------+
              ^
             / \
            +---+
              |
              |
    +-------------------+
    |   Cuadrilátero    |
    | de ángulos rectos |
    +-------------------+
      ^               ^
     / \             / \
    +---+           +---+
      |               |
      |               |
 +----------+  +------------+
 | Cuadrado |  | Rectángulo |
 +----------+  +------------+

 Se podrían unificar las clases Cuadrilátero y "Cuadrilatero de ángulos 
rectos", pero entonces podríamos encontrarnos con dificultades parecidas al 
tratar de modelar a la vez Cuadrado y Rombo, aunque curiosamente la intuición 
funciona mejor para éste caso, y no tratámos de pensar que "un cuadrado es un 
cierto tipo de rombo".
 Es recomendable definir la herencia como una relación de pertenencia obvia, 
sin casos particulares, ya que de lo contrario podemos llevarnos sorpresas. 
 En concreto, en el libro citado se analiza el problema como una violación 
sutil del Principio de Sustitución de Liskov: "Subtipos deben ser 
reemplazables por sus tipos base". El análisis se basa, como es frecuente en 
nuestros días, en una visión prágmatica, consistente en mostrar las 
incongruencias en las que se incurren al aplicar el citado principio en el 
modelo de clases original. De hecho, incluso se llega a la conclusión de que 
la validez del modelo depende de un tercero: el código que recibe 
indistintamente un Cuadrado o un Rectángulo, y que sin embargo percibe que 
ambos no se comportan igual. En otras palabras: un cuadrado es o no es un 
rectángulo dependiendo del punto de vista de quién los use.
 Este es un buen ejemplo que muestra en lineas generales mi opinión del libro: 
tiene cosas interesantes, pero te va dando bofetadas sin parar.
 Si alguno lo quiere, lo regalo/presto/vendo (depende de lo que os resulte más 
cómodo).

 [1] Agile Software Development. Principles, Patterns, and Practices. Robert 
C. Martin.