¿Cómo difiere la herencia del subtipo?


15

En la perspectiva del lenguaje de programación, ¿qué significa subtipo? Escuché que "La herencia no es subtipo". Entonces, ¿cuáles son las diferencias entre herencia y subtipo?


66
Me pregunto si esta pregunta (y otras similares) podrían redirigirse al nuevo sitio cs.SE cuando entre en beta pública.
Suresh Venkat

1
Bienvenido a cstheory, un sitio de preguntas y respuestas para preguntas de nivel de investigación en informática teórica (TCS). Su pregunta no parece ser una pregunta de nivel de investigación en TCS. Consulte las preguntas frecuentes para obtener más información sobre lo que se entiende por esto y sugerencias para los sitios que podrían recibir su pregunta. Finalmente, si su pregunta está cerrada por estar fuera de alcance, y cree que puede editarla para que sea una pregunta de nivel de investigación, no dude en hacerlo. El cierre no es permanente y las preguntas se pueden volver a abrir, consulte las Preguntas frecuentes para obtener más información.
Kaveh

3
@UdayReddy: Ninguna pregunta no fue trivial cuando se respondió por primera vez, pero debemos tomar una decisión desde el punto de vista moderno. El mismo argumento que el suyo implicaría que la pregunta sobre el algoritmo de Dijkstra es sobre el tema porque el primer artículo habla sobre él y nada más.
Tsuyoshi Ito

3
@TsuyoshiIto La analogía no es apropiada porque el primer artículo de Dijkstra resolvió el problema, mientras que el primer artículo de Cardelli aquí creó el problema. Aún así, considero que no medimos el estado del arte basado en el primer artículo. Permítanme asegurarles que las diferencias entre la herencia y el subtipo no representan un problema resuelto, y anticipo que el tema se debatirá durante al menos otros 20 años. Se le puede recomendar al interrogador que haga una tarea adicional y que edite la pregunta para aclarar los problemas a nivel de investigación.
Uday Reddy

3
En cualquier caso, es bastante fácil señalar el OP al documento de Cook et al. Del mismo nombre: citeseerx.ist.psu.edu/viewdoc/summary?doi=10.1.1.102.8635
Andreas Rossberg

Respuestas:


18

[No he pensado profundamente en los problemas de los sistemas de tipos orientados a objetos, pero diré lo que sé para iniciar la discusión.]

Decimos que es un subtipo de B si todos los valores de tipo A se pueden usar en todos los contextos donde se esperan valores de tipo B. O, para decirlo de otra manera, los valores de tipo A pueden "enmascararse" como valores de tipo B.UNsiUNsiUNsi

Si tal enmascaramiento no plantea problemas con la verificación de tipos, es decir, la conexión de valores con tipo donde se necesitan valores con tipo B continúa con la verificación de tipo, lo llamamos "subtipo estructural" . Si no causa problemas con el comportamiento, es decir, este tipo de conexión no altera el comportamiento esperado, entonces lo llamamos "subtipo de comportamiento" . (El "comportamiento esperado" deberá formalizarse por separado y son posibles muchas nociones de comportamiento).UNsi

El subtipo estructural no garantiza el subtipo de comportamiento porque la estructura de un tipo puede coincidir por razones accidentales. Sin embargo, definir el comportamiento esperado no es fácil. Entonces, muchos lenguajes de programación usan un punto intermedio, donde el usuario tiene que declarar qué tipo es un subtipo de cuál. Esto se conoce como "subtipo nominal" . Vea la pregunta sobre Subtipo implícito vs explícitopara una discusión de este tema. La idea es que el programador debe garantizar el subtipo de comportamiento para todos los subtipos declarados utilizando su propio ingenio. El idioma no puede ofrecer ninguna ayuda. Sin embargo, todos los subtipos declarados deben ser al menos subtipos estructurales. De lo contrario, el programa no podría escribir check. El lenguaje puede ayudar a garantizar esto. (Algunos lenguajes de programación no tienen sistemas de tipos lo suficientemente buenos como para garantizar esto en tiempo de compilación. Si es así, la falla de tipo se detectaría en tiempo de ejecución, o tal vez se podrían producir resultados incorrectos. Tales agujeros de tipo son obviamente indeseables).

Cuando uno define subclases en programas orientados a objetos, normalmente agrega campos (o métodos) visibles públicamente. En la mayoría de los lenguajes de programación, tales subclases se consideran subtipos nominales . La pregunta es si también son subtipos estructurales . Si no lo son, es decir, el lenguaje de programación le permite a uno declarar subtipos nominales que no son subtipos estructurales, entonces habría agujeros de tipo en el lenguaje de programación.

En casos simples, agregar campos funciona bien. El tipo de la superclase espera menos campos que el tipo de la subclase. Por lo tanto, si conecta una instancia de una subclase donde se espera una instancia de la sueprclass, el programa simplemente ignorará los campos adicionales proporcionados y nada sale mal.

Sin embargo, si la superclase o subclase tiene métodos que toman argumentos del mismo tipo en sí mismos o devuelven resultados del mismo tipo en sí mismos, entonces surgen problemas. Entonces, el tipo de interfaz de la subclase no es un subtipo estructural del de la superclase. Los lenguajes de programación de tipo seguro ampliamente utilizados, como Java, no permiten tales subclases. Por lo tanto, restringen el idioma para obtener la seguridad de tipo. Se dice que el lenguaje de programación Eiffel ha sacrificado la seguridad de tipos para obtener flexibilidad . Si se diseña un sistema de tipo fuerte que conserva la flexibilidad, se debe abandonar el principio de que las subclases dan lugar a subtipos. De ahí el título del artículo "La herencia no es subtipo". Los autores proponen una noción diferente de subtipo de orden superior que funciona en su lugar. Kim Bruce también tiene una propuesta estrechamente relacionada llamada "coincidencia" que logra el mismo efecto. Ver esta presentación . También es útil un documento de posición de Andrew Black.

La comunidad semántica probablemente tenga la culpa de ignorar en gran medida el problema. Tradicionalmente lo hemos considerado como un problema práctico de ingeniería de sistemas de tipos que tiene poco interés teórico. Si ese no es el caso y de hecho hay trabajo semántico en el área, espero que las otras personas los mencionen.


1
Quizás también valga la pena mencionar que existen idiomas reales que han desacoplado con éxito los subtipos de la herencia, por ejemplo, Ocaml en su sistema de objetos.
Andreas Rossberg

@AndreasRossberg De hecho, OCaml no estaba en mi marco cuando escribí esa respuesta. Supongo que OCaml no tiene subtipo nominal en absoluto. Entonces, algunos de estos problemas no surgirían. Pero existe la posibilidad de que los tipos coincidan accidentalmente, incluso si el comportamiento no lo hace, y el sistema de tipos no podrá ayudar a detectar errores de ese tipo.
Uday Reddy
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.