Pregunta

Estoy tratando de entender si la respuesta a la siguiente pregunta es la misma en todos los principales idiomas OOP; Y si no, ¿cómo difieren esos idiomas?

Supongamos que tengo clase A que define métodos act y jump; método act Método de llamadas jump. ASubclase B Método de anulación jump (es decir, la sintaxis apropiada se usa para garantizar que siempre que jump se llama, la implementación en clase B se usa).

Tengo objeto b de clase B. Quiero que se comporte exactamente como si fuera de clase A. En otras palabras, quiero el jump para realizarse utilizando la implementación en A. ¿Cuáles son mis opciones en diferentes idiomas?

Por ejemplo, ¿puedo lograr esto con alguna forma de descendencia? ¿O tal vez creando un objeto proxy que sepa qué métodos llamar?

Me gustaría evitar crear un nuevo objeto de clase. A y establecer cuidadosamente el intercambio de estado interno entre a y b Porque eso obviamente no es a prueba de futuro y complicado. También me gustaría evitar copiar el estado de b en un nuevo objeto de clase A Porque puede haber muchos datos para copiar.

ACTUALIZAR

Hice esta pregunta específicamente sobre Python, Pero parece que esto es imposible de lograr en Python y técnicamente se puede hacer ... un poco ...

Parece que, aparte de la viabilidad técnica, hay un fuerte argumento en contra de hacerlo desde una perspectiva de diseño. Estoy preguntando por eso en una pregunta separada.

¿Fue útil?

Solución

Los comentarios reiterados: prefieren la composición sobre la herencia.

La herencia funciona bien cuando sus subclases tienen diferencias de comportamiento bien definidas de su superclase, pero con frecuencia alcanzará un punto en el que ese modelo se vuelva incómodo o deje de tener sentido. En ese momento, debe reconsiderar su diseño.

La composición suele ser la mejor solución. Delegar el comportamiento variable de su objeto a un objeto diferente (u objetos) puede reducir o eliminar su necesidad de subclase.

En su caso, las diferencias de comportamiento entre la clase A y la clase B podrían encapsularse en el patrón de estrategia. Luego puede cambiar el comportamiento de la clase A (y la clase B, si aún es necesario) en el nivel de instancia, simplemente asignando una nueva estrategia.

El patrón de estrategia puede requerir más código a corto plazo, pero es limpio y mantenible. Método Swizzling, Monkey Patching y todas esas cosas geniales que nos permiten hundir en nuestra implementación de lenguaje específico son divertidos, pero el potencial de efectos secundarios inesperados es alto y el código tiende a ser difícil de mantener.

Otros consejos

Lo que está preguntando no es relacionado/sin apoyo por la programación OOP.

Si subclase un objeto A con clase B y anular sus métodos, cuando una instancia concreta de B Se crea, entonces toda la implementación de anulación/nueva de los métodos base está asociada con él (o hablamos de Java o C ++ con tablas virtuales, etc.).

Tienes objeto instanciado B.
¿Por qué esperaría que podría/debería/debería poder llamar al método de la superclase si ha anulado ese método?

Podrías llamarlo explícito, por supuesto, por ejemplo, llamando super Dentro del método, pero no puede hacerlo automáticamente, y el casting tampoco lo ayudará a hacerlo.

No puedo imaginar por qué querrías hacer eso.
Si necesitas usar la clase A Entonces usa la clase A.
Si necesita anular su funcionalidad, use su subclase B.

La mayoría de los lenguajes de programación tienen problemas para respaldar el envío dinámico de las funciones virtuales (el caso de llamar al método anulado jump En una subclase en lugar de la implementación de la clase principal), en el grado en que trabajar en su alrededor o evitarla es difícil. En general, la especialización/polimorfismo es una característica deseable, posiblemente un objetivo de OOP en primer lugar.

Echa un vistazo al artículo de Wikipedia en Funciones virtuales, que ofrece una visión general útil del soporte para funciones virtuales en muchos lenguajes de programación. Le dará un lugar para comenzar al considerar un lenguaje específico, así como las compensaciones para pesar al mirar un lenguaje donde el programador puede controlar cómo se comporta el despacho (consulte la sección sobre C ++, por ejemplo).

Tan libremente, la respuesta a su pregunta es: "No, el comportamiento no es el mismo en todos los lenguajes de programación". Además, no hay una solución independiente del lenguaje. C ++ puede ser tu mejor opción si necesitar el comportamiento.

En realidad, puedes hacer esto con Python (más o menos), con algunos trucos horribles. Requiere que implementa algo como los envoltorios que estábamos discutiendo en su primera pregunta específica de Python, pero como una subclase de B. Luego también debe implementar la protección contra la escritura (el objeto Wrapper no debe contener ninguno de los estados normalmente asociados con la jerarquía de clases, debe redirigir todo el acceso de atributos a la instancia subyacente de B.

Pero en lugar de redirigir la búsqueda del método a A y luego llamar al método con la instancia envuelta, llamaría el método que pase el objeto de envoltura como self. Esto es legal porque la clase de envoltorio es una subclase de B, por lo que la instancia de envoltura es una instancia de las clases cuyos métodos está llamando.

Este sería un código muy extraño, lo que exigiría que genere dinámicamente clases utilizando las relaciones IS-A y HA-A al mismo tiempo. Probablemente también terminaría bastante frágil y tenga resultados extraños en muchos casos de esquina (generalmente no puede escribir clases de envoltura 100% perfectas en Python exactamente porque este tipo de cosa extraña es posible).

Dejo completamente a un lado el clima, esta es una buena idea o no.

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top