¿Hay algún idioma OO sin herencia?

22

Durante una revisión de código hoy, un colega mío dijo algo interesante:

prototypesolo es útil cuando necesita herencia, y ¿ cuándo es una buena idea la herencia ?

Pensé en esto y me di cuenta de que generalmente uso la herencia para evitar el código mal diseñado en primer lugar. El estilo OO moderno prefiere la composición sobre la herencia, pero no conozco ningún idioma que haya tomado esto en serio y realmente lo imponga .

¿Hay algún lenguaje de programación de propósito general con clases, objetos, métodos, interfaces, etc., que no permita la herencia basada en clases? (Si tal idea no tiene sentido, ¿por qué no?)

Benjamin Hodgson
fuente
77
Tu colega te ha llevado por mal camino. Esto prototypetambién es útil para cuando tiene métodos públicos y propiedades que deben compartirse entre instancias. También es útil porque permite utilizar adecuadamente el instanceofoperador en JavaScript: if (foo instanceof Foo) { ....
Greg Burghardt
2
Creo que deberíamos hacer una distinción entre la herencia de tipo, estado y comportamiento. La preferencia de composición es muy común en la comunidad Java, pero al mismo tiempo, la herencia (e incluso la herencia múltiple) de tipos se usa y fomenta ampliamente ... y se realiza utilizando la implementspalabra clave y las interfaces (en oposición a la herencia de estado y comportamiento introducido con el uso de la extendspalabra clave en clases que contienen cualquier implementación).
toniedzwiedz
66
Preferir la composición no significa abandonar por completo la herencia es una buena idea.
Caleb
55
ver Java sin la herencia de implementación : "Ir de Google es un ejemplo de un lenguaje que elimina la herencia de implementación al tiempo que la POO ..."
mosquito
1
@GregBurghardt Lo mismo puede lograrse con una función de fábrica que devuelve un objeto que contiene funciones (almacenando datos privados en el cierre). new, thisy prototypeson demasiado de un campo de minas para uso común IMO.
Benjamin Hodgson

Respuestas:

18

Dejando a un lado la cuestión de la definición de programación orientada a objetos, la pregunta se convierte en una de "¿existen lenguajes que usan solo composición y no tienen herramientas para la herencia?"

La respuesta a esto es simplemente "sí". En el camino, no hay forma de hacer la herencia como se piensa clásicamente. Uno puede incrustar un objeto en otro objeto y extender ese objeto. Del lenguaje desorientado de objetos ( espejo github ):

type Person struct {
        Name string
}

func (p *Person) Intro() string {
        return p.Name
}

type Woman struct {
        Person
}

func (w *Woman) Intro() string {
        return "Mrs. " + w.Person.Intro()
}

Tienes una estructura de persona que tiene un Nombre que es una Cadena. Tiene una función pública llamada Introducción que devuelve el nombre. La estructura Woman también tiene una función para Intro que accede al puntal incrustado en ella. Y entonces uno puede cumplir las intenciones de la herencia usando solo la composición.

Se puede ver más sobre esto en los Tutoriales de GoLang: Herencia y subclases en Go, o su parecido cercano .

Entonces, sí, es posible tener un lenguaje OO sin herencia, y existe uno.

Dentro de ir, esto se conoce como incrustación y le da a las estructuras envolventes la capacidad de acceder a los campos incrustados y funciona como si también los tuviera, pero no es una subclase. La filosofía de diseño se puede encontrar en las Preguntas frecuentes de Go: ¿Por qué no hay herencia de tipo?


fuente
También se podría comentar sobre el uso de typedefy structen C ...
cwallenpoole
@cwallenpoole hay ideas similares allí, aunque dudaría en llamar a C un lenguaje orientado a objetos.
No se. Admito el hecho de que no puedes crear objetos con funciones adjuntas funciona en su contra, pero sin herencia, OOP pierde gran parte de su sabor.
cwallenpoole
@cwallenpoole y comenzamos a definir qué es herencia y orientación de objeto. Pero es posible, es solo una forma diferente de pensar sobre el problema. La cuestión es que la herencia es la forma en que la mayoría de los programadores de C ++ y Java piensan en la extensión ... pero hay otros modelos. Extensión sin herencia: 1 , 2 , 3 son buenas lecturas.
El enlace al "Lenguaje desorientado de objetos" está atascado en un bucle de redireccionamiento en este momento, pero encontré el artículo aquí: github.com/nu7hatch/areyoufuckingcoding.me/blob/master/content/… . ¡Gracias!
Matt Browne el
7

¿Hay algún lenguaje de programación de propósito general con clases, objetos, métodos, interfaces, etc., que no permita la herencia basada en clases?

Esto se parece mucho a una descripción de VBA: Visual Basic para aplicaciones, integrado en Microsoft Office y otros hosts habilitados para VBA (por ejemplo, AutoCAD, Sage 300 ERP, etc.), o incluso VB6. La "A" de "Básico" significa "Uso múltiple" de todos modos, por lo que está la parte "uso general".

VB6 / VBA tiene clases (y, por lo tanto, objetos), métodos e interfaces; podría definir una ISomethinginterfaz en un módulo de clase como este:

Option Explicit

Public Sub DoSomething()
End Sub

Y luego tenga otra clase que haga esto:

Option Explicit
Implements ISomething

Private Sub ISomething_DoSomething()
    'implementation here
End Sub

A tal clase, sin exponer a ningún miembro público, solo se podía acceder a través de su ISomethinginterfaz, y podría haber docenas de implementaciones diferentes ISomething, por lo que el código OOP VBA es perfectamente capaz de polimorfismo, y es perfectamente legal para una clase determinada. para implementar múltiples interfaces, también.

Sin embargo, VB6 / VBA no permite la herencia de clases , por lo que no puede heredar una implementación de otro tipo, solo su interfaz. Ahora, si esto es un accidente, un defecto de diseño, un golpe de genio o una gran supervisión fea está abierto a debate; no está claro si VB6 / VBA se toma esto en serio , pero definitivamente lo hace cumplir .

Si Go no hace herencia de clases y, sin embargo, es un lenguaje OOP , entonces no veo por qué VB6 / VBA no podría considerarse también un lenguaje OOP.</PreemptiveResponseToVBAHatersThatWillSayItIsNotAnOOPLanguage>

Mathieu Guindon
fuente
1
Para ser justos, OP preguntó sobre los idiomas modernos . =;) -
RubberDuck
@RubberDuck #burn!
Mathieu Guindon
0

Puede hacer que el compilador imponga la herencia selectiva mediante el uso de técnicas privadas / protegidas, y mediante el uso moderno de técnicas "PImpl" o "Implementación privada".

Muchas API exponen solo aquellos componentes que desea que un usuario herede, y ocultan el resto en una clase de implementación separada. Por lo tanto, podría escribir clases cuyas interfaces públicas sean, de hecho, no heredables, solo utilizables a través de la composición de objetos y forzadas por el compilador. Esto suele ser una buena práctica, cuando utiliza el compilador para hacer cumplir la intención del software.

Una búsqueda rápida de funciones para miembros privados en JavaScript muestra que hay un principio similar, aunque cualquiera puede ver su código si puede usarlo: http://www.crockford.com/javascript/private.html

Ruan Caiman
fuente