En la representación del conocimiento , la programación y el diseño orientados a objetos (ver arquitectura de programas orientados a objetos ), is-a ( is_a o is a ) es una relación de subsunción [1] entre abstracciones (por ejemplo , tipos , clases ), donde una clase A es una subclase de otra clase B (por lo que B es una superclase de A ). En otras palabras, el tipo A es un subtipo del tipo B cuando A la especificación implica la especificación de B. Es decir, cualquier objeto (o clase) que satisfaga la especificación de A también satisface la especificación de B, porque la especificación de B es más débil. [2]
La es-a relación debe ser contrastado con el tiene-a ( has_a o tiene una ) relación entre los tipos (clases); confundir las relaciones tiene-a y es-a es un error común al diseñar un modelo (por ejemplo, un programa de computadora ) de la relación del mundo real entre un objeto y su subordinado. La relación es-a también puede contrastarse con la relación instancia-de entre objetos (instancias) y tipos (clases): consulte Distinción tipo-token .
Para resumir las relaciones, hay:
- hiperónimo - hipónimo (supertipo / superclase-subtipo / subclase) relaciones entre tipos (clases) que definen una jerarquía taxonómica, donde
- para una relación de subsunción : un hipónimo (subtipo, subclase) tiene una relación tipo-de ( es-a ) con su hiperónimo (supertipo, superclase);
- holónimo - merónimo (todo / entidad / contenedor-parte / constituyente / miembro) relaciones entre tipos (clases) que definen una jerarquía posesiva, donde
- para una relación de agregación (es decir, sin propiedad):
- un holónimo (todo) tiene una relación tiene-a con su merónimo (parte),
- para una relación de composición (es decir, con propiedad):
- un merónimo (constituyente) tiene una relación parcial con su holónimo (entidad),
- para una relación de contención [3] :
- un merónimo (miembro) tiene una relación de miembro de con su holónimo ( contenedor );
- para una relación de agregación (es decir, sin propiedad):
- relaciones concepto-objeto (tipo-token) entre tipos (clases) y objetos (instancias), donde
- un token (objeto) tiene una relación de instancia con su tipo (clase).
Ejemplos de subtipificación
La subtipificación permite sustituir un tipo determinado por otro tipo o abstracción. Se dice que el subtipo establece una relación es-a entre el subtipo y alguna abstracción existente, ya sea implícita o explícitamente, dependiendo del soporte del lenguaje. La relación se puede expresar explícitamente mediante herencia en lenguajes que admiten la herencia como mecanismo de subtipificación.
C ++
El siguiente código de C ++ establece una relación de herencia explícita entre las clases B y A , donde B es una subclase y un subtipo de A , y se puede usar como A siempre que se especifique una B (a través de una referencia, un puntero o el objeto mismo ).
clase A { public : void DoSomethingALike () const {} };clase B : public A { public : void DoSomethingBLike () const {} };void UseAnA ( A const & some_A ) { some_A . DoSomethingALike (); }anular SomeFunc () { B b ; UseAnA ( b ); // b se puede sustituir por A. }
Pitón
El siguiente código de Python establece una relación de herencia explícita entre las clases B y A , donde B es una subclase y un subtipo de A , y se puede usar como A siempre que se requiera una B.
clase A : def do_something_a_like ( self ): passclase B ( A ): def hacer_algo_b_como ( yo ): pasardef use_an_a ( some_a ): some_a . hacer_algo_un_como ()def some_func (): b = B () use_an_a ( b ) # b puede ser sustituido por A.
En el siguiente ejemplo, el tipo (a) es un tipo "regular" y el tipo (tipo (a)) es un metatipo. Si bien todos los tipos distribuidos tienen el mismo metatipo ( PyType_Type , que también es su propio metatipo), esto no es un requisito. El tipo de clases clásicas, conocidas como types.ClassType , también se puede considerar un metatipo distinto. [5]
>>> a = 0 >>> tipo ( a ) >>> tipo ( tipo ( a )) >>> tipo ( tipo ( tipo ( a ))) >>> tipo ( tipo ( tipo ( tipo ( a ))))
Java
En Java, es una relación entre los parámetros de tipo de una clase o interfaz y los parámetros de tipo de otra están determinados por las cláusulas extend e implementa .
Usando las clases de Colecciones, ArrayList
interfaz PayloadList < E , P > extiende List < E > { void setPayload ( int index , P val ); ... }
Las siguientes parametrizaciones de PayloadList son subtipos de List
PayloadList < String , String > PayloadList < String , Integer > PayloadList < String , Exception >
Principio de sustitución de Liskov
El principio de sustitución de Liskov explica una propiedad, "Si para cada objeto o1 de tipo S hay un objeto o2 de tipo T tal que para todos los programas P definidos en términos de T, el comportamiento de P no cambia cuando o1 se sustituye por o2 entonces S es un subtipo de T, " . [6] El siguiente ejemplo muestra una violación de LSP.
void DrawShape ( const Shape & s ) { if ( typeid ( s ) == typeid ( Cuadrado )) DrawSquare ( static_cast < Cuadrado &> ( s )); else if ( typeid ( s ) == typeid ( Circle )) DrawCircle ( static_cast < Circle &> ( s )); }
Obviamente, la función DrawShape está mal formateada. Tiene que conocer todas las clases derivadas de la clase Shape. Además, debe cambiarse siempre que se cree una nueva subclase de Shape. En el diseño orientado a objetos , muchos [ ¿quién? ] ven la estructura de esto como un anatema.
Aquí hay un ejemplo más sutil de violación de LSP:
class Rectangle { public : void SetWidth ( doble w ) { itsWidth = w ; } void SetHeight ( doble h ) { itsHeight = h ; } double GetHeight () const { return itsHeight ; } double GetWidth () const { devuelve su ancho ; } privado : doble su ancho ; el doble de su altura ; };
Esto funciona bien, pero cuando se trata de la clase Square, que hereda la clase Rectangle, viola LSP aunque la relación is-a se mantiene entre Rectangle y Square. Porque el cuadrado es rectangular. El siguiente ejemplo anula dos funciones, Setwidth y SetHeight, para solucionar el problema. Pero arreglar el código implica que el diseño es defectuoso.
clase pública Cuadrado : Rectángulo { público : vacío virtual SetWidth ( doble w ); SetHeight vacío virtual ( doble h ); }; vacío Cuadrado :: SetWidth ( doble w ) { Rectangle :: SetWidth ( w ); Rectángulo :: SetHeight ( w ); } vacío Square :: SetHeight ( doble h ) { Rectángulo :: SetHeight ( h ); Rectángulo :: SetWidth ( h ); }
En el siguiente ejemplo, la función g solo funciona para la clase Rectangle pero no para Square, por lo que se ha violado el principio de abierto-cerrado.
void g ( Rectángulo & r ) { r . SetWidth ( 5 ); r . SetHeight ( 4 ); afirmar ( r . GetWidth () * r . GetHeight ()) == 20 ); }
Ver también
- Herencia (programación orientada a objetos)
- Principio de sustitución de Liskov (en programación orientada a objetos )
- Subsunción
- Es un
- Hipernimia (y supertipo )
- Hiponimia (y subtipo )
- Tiene un
- Holonimia
- Meronimia
Notas
- ^ Ver principio de sustitución de Liskov .
- ^ "Subtipos y subclases" (PDF) . MIT OCW . Consultado el 2 de octubre de 2012 .
- ^ Consulte también Contención (programación de computadoras) .
- ^ Mitchell, John (2002). "10" Conceptos en lenguajes orientados a objetos " ". Conceptos en lenguaje de programación . Cambridge, Reino Unido: Cambridge University Press. pag. 287. ISBN 0-521-78098-5.
- ^ Guido van Rossum. "Subtipado de tipos integrados" . Consultado el 2 de octubre de 2012 .
- ^ Liskov, Barbara (mayo de 1988). Jerarquía y abstracción de datos (PDF) . Avisos SIGPLAN.
- ^ "El principio de sustitución de Liskov" (PDF) . Robert C. Martin, 1996. Archivado desde el original (PDF) el 5 de septiembre de 2015 . Consultado el 2 de octubre de 2012 .
Referencias
- Ronald J. Brachman ; Qué es y qué no es IS-A. Un análisis de vínculos taxonómicos en redes semánticas . Computadora IEEE, 16 (10); Octubre de 1983
- Jean-Luc Hainaut, Jean-Marc Hick, Vincent Englebert, Jean Henrard, Didier Roland: Comprensión de las implementaciones de las relaciones IS-A . ER 1996: 42-57