¿Por qué muchos lenguajes de programación dinámica de tipo pato utilizan un enfoque basado en clases en lugar de OOP basado en prototipos?

23

Dado que muchos lenguajes de programación dinámicos tienen la característica de escribir pato , y también pueden abrir y modificar métodos de clase o instancia en cualquier momento (como Ruby y Python ), entonces ...

Pregunta 1) ¿Cuál es la necesidad de una clase en un lenguaje dinámico? ¿Por qué el lenguaje está diseñado de esa manera para usar una clase como una especie de "plantilla" en lugar de hacerlo como prototipo y simplemente usar un objeto?

También JavaScript está basado en prototipos, pero CoffeeScript (la versión mejorada de JavaScript) elige la forma basada en clases. Y es lo mismo para Lua (basado en prototipos) y MoonScript (basado en clases). Además, hay clase en ES 6. Entonces ...

Pregunta 2) ¿Sugiere que si intentas mejorar un lenguaje basado en prototipos, entre otras cosas, deberías cambiarlo a clases? Si no, ¿por qué está diseñado de esa manera?

iceX
fuente
99
Muchos programadores no quieren molestarse en aprender algo nuevo. (Es demasiado extraño y "difícil"). De ahí todas esas bibliotecas y lenguajes basados ​​en clases que se compilan para ellos.
Thomas Eding
1
Estoy de acuerdo con Thomas, pero lo gracioso es que después de aprender el enfoque dinámico, en realidad es más fácil (no más difícil). El concepto de objetos todavía está ahí, es solo que los objetos pueden cambiarse sin recompilar algún "plano" estúpido primero. Si quiero poner una quinta pata en una silla, no quiero tener que alterar un plano primero, solo quiero agregar la pata. Los lenguajes dinámicos modelan más la realidad en mi opinión.
Lonnie Best
1
OOP se inventó en un contexto de tipo estático, donde los tipos deben declararse. Allí, las clases son un paso sensato hacia adelante desde los registros y los módulos. La OOP basada en prototipos siempre fue un tema de investigación interesante para el lenguaje Self, y de alguna manera se convirtió en JavaScript como la forma más simple de marcar la palabra de moda "OOP" para un lenguaje esencialmente funcional. Lo bueno es que puedes implementar clases sobre prototipos. Si bien me gustan los metaobjetos, separar las clases de sus instancias hace que sea más fácil escribir código bien factorizado, simple y poco acoplado.
amon
3
Lo primero es lo primero: JavaScript admite la classpalabra clave a partir del próximo estándar ECMAScript (ECMAScript 6). El soporte para las clases en JavaScript se ha planificado durante mucho tiempo. Ahora, para lo que es, las clases son simplemente azúcar sintáctica, una forma más fácil de razonar sobre modelos para objetos del mismo tipo. Es así en JS y así en Python y otros lenguajes dinámicos.
Benjamin Gruenbaum
1
@BenjaminGruenbaum "... las clases son simplemente azúcar sintáctica ..." wow, esta es una idea bastante novedosa para mí, realmente, para lenguajes como ruby ​​y python, parece que no importa si usar un objeto o clase como plantilla: ambos pueden modificarse sobre la marcha de todos modos. Y en realidad tampoco importa cómo manejan la herencia. Entonces, tal vez no sea necesario distinguir entre el enfoque basado en la clase y el enfoque basado en el prototipo para un lenguaje dinámico :)
iceX

Respuestas:

12

Pregunta 1) ¿Cuál es la necesidad de una clase en un lenguaje dinámico? ¿Por qué el lenguaje está diseñado de esa manera para usar una clase como una especie de "plantilla" en lugar de hacerlo como prototipo y simplemente usar un objeto?

El primer lenguaje OO (aunque no se llamaba "OO"), Simula, no tenía herencia. La herencia se agregó en Simula-67, y se basó en clases.

Al mismo tiempo, Alan Kay comenzó a trabajar en su idea de un nuevo paradigma de programación, que más tarde llamó "Orientación a objetos". Realmente le gustaba la herencia y quería tenerla en su idioma, pero tampoco le gustaban las clases. Sin embargo, no podía encontrar una forma de tener herencia sin clases, por lo que decidió que no le gustaban las clases más de lo que le gustaba la herencia y diseñó la primera versión de Smalltalk, Smalltalk-72 sin clases y, por lo tanto, sin herencia.

Un par de meses después, a Dan Ingalls se le ocurrió un diseño de clases, donde las clases mismas eran objetos, a saber, instancias de metaclases. Alan Kay encontró este diseño un poco menos desalentador que los anteriores, por lo que Smalltalk-74 fue diseñado con clases y con una herencia basada en clases.

Después de Smalltalk-74, Alan Kay sintió que Smalltalk se estaba moviendo en la dirección equivocada y en realidad no representaba de qué se trataba OO, y propuso que el equipo abandonara Smalltalk y comenzara de nuevo, pero fue votado. Así siguieron Smalltalk-76, Smalltalk-80 (la primera versión de Smalltalk que se lanzará a los investigadores), y finalmente Smalltalk-80 V2.0 (la primera versión que se lanzará comercialmente, y la versión que se convirtió en la base de ANSI Smalltalk) .

Dado que Simula-67 y Smalltalk-80 se consideran los abuelos de todos los idiomas OO, casi todos los idiomas que siguieron, copiaron ciegamente el diseño de las clases y la herencia en función de las clases. Un par de años más tarde, cuando surgieron otras ideas como la herencia basada en mixins en lugar de clases, y la delegación basada en objetos en lugar de la herencia basada en clases, la herencia basada en clases ya se había arraigado demasiado.

Curiosamente, el lenguaje actual de Alan Kay se basa en la delegación de prototipos.

Jörg W Mittag
fuente
"... el idioma actual de Alan Kay ..." que es ...?
Javier
@Javier: No creo que tenga un nombre, y el nombre del sistema sigue cambiando.
Jörg W Mittag
Esta debería ser una buena respuesta para señalar la próxima vez que alguien mencione la herencia como un requisito para OO :)
Hola,
1
@iceX: Alan Kay fundó el Viewpoints Research Institute para trabajar en sus ideas. Desafortunadamente, la información está realmente dispersa en el sitio web.
Jörg W Mittag
3
La cita de Alan Kay sobre OO: "OOP para mí significa solo mensajes, retención local y protección y ocultación del proceso estatal, y un enlace tardío extremo de todas las cosas. Se puede hacer en Smalltalk y en LISP. Posiblemente hay otros sistemas en lo cual es posible, pero no estoy al tanto de ellos ".
Joeri Sebrechts
23

Muchos programadores prefieren trabajar con clases. Es un concepto muy fácil de entender que es un buen modelo de procesos de pensamiento humano sobre el mundo (es decir, instintivamente relacionamos objetos reales con el grupo abstracto de elementos a los que consideramos que pertenecen, que es lo que es una clase) . Además, las clases facilitan el razonamiento sobre los tipos de objetos: en un lenguaje basado en clases, la aplicación de principios como la sustitución de Liskov es más simple que en un lenguaje en el que solo tenemos objetos que pueden tener diferentes métodos, o cuyo tipo puede incluso cambiar en el tiempo de ejecución , como es el caso en JavaScript.

Tenga en cuenta que incluso en JavaScript, una gran cantidad de código simplemente usa el prototipo para emular clases. Esto se debe principalmente a que muchos programadores prefieren pensar de esa manera.

También hay otra razón por la que se prefieren los lenguajes basados ​​en clases: es más fácil compilarlos en un código eficiente. Las máquinas virtuales JavaScript más eficientes crean clases dinámicamente para representar los tipos de objetos JavaScript a medida que cambian sus métodos y prototipos. Consulte esta descripción de la implementación de V8 para obtener una explicación de por qué se hace esto.

Jules
fuente
44
Su último párrafo en realidad admite exactamente lo contrario de lo que está diciendo: V8 demuestra que no necesita clases en el idioma para compilar un código eficiente basado en clases.
Jörg W Mittag
44
Sí, no los necesita, pero el hecho de que V8 (y presumiblemente Self, aunque no he leído mucho sobre el diseño de ese sistema) efectivamente crea clases virtuales significa que comenzar desde un lenguaje que usa las clases de forma nativa es casi ciertamente más fácil, y por lo tanto probablemente terminaría con la necesidad de que JIT dedique menos tiempo a compilar el código.
Julio
11
Claro, y el hecho de que V8 crea GOTOy registra efectivamente significa que simplemente abandonar todas las abstracciones y escribir directamente en el ensamblaje es casi seguro, y por lo tanto, probablemente el JIT necesite pasar menos tiempo compilando el código. Es el trabajo de un compilador para soportar abstracciones de alto nivel.
Jörg W Mittag
1
Sí, pero es una compensación, ya que la abstracción de nivel superior es en la mayoría de los casos más difícil de implementar y a menudo tiene una penalización de rendimiento en tiempo de ejecución, especialmente cuando se trabaja con un JIT en lugar de un compilador AOT. Sospecho que muchos diseñadores de idiomas eligen una estructura basada en clases por uno o ambos motivos; Sé que es por eso que elegí clases con miembros fijos para el lenguaje (por lo demás dinámico) en el que estoy trabajando, pero solo puedo especular sobre otros idiomas.
Jules
1
Yo diría que la única forma en que los programadores prefieren "pensar en clases" es porque así es como se nos enseña a la mayoría de nosotros. Sin embargo, definitivamente puedo recordar a muchos de mis compañeros estudiantes en la universidad que tuvieron problemas para comprender y comprender algunos conceptos orientados a objetos realmente fundamentales durante varios años. Solo parece obvio y fácil en retrospectiva.
KChaloux
3

He oído que en grandes proyectos, donde equipos de personas trabajan juntos en el mismo código, que los lenguajes flexibles (donde puedes modificar las propiedades y métodos de un objeto durante el tiempo de ejecución) son libertades que otros miembros del equipo no te quieren. tener.

Quieren saber, cuando se trata de un objeto, que el objeto actuará tal como lo dice el plano, y no de una manera transformada a la que algún otro desarrollador ambicioso decidió cambiarlo para completar su propia tarea.

Entonces, la única razón por la que puedo concebir, que alguien no querría las flexibilidades que ofrecen estos impresionantes lenguajes dinámicos, es que quieren simplificar el desarrollo, la depuración y la documentación automática del equipo.

Personalmente, he desarrollado aplicaciones en ambas metodologías, y hago las cosas mucho más rápido con lenguajes dinámicos. No uso ninguno de estos marcos diseñados para volver a convertir mi lenguaje dinámico en un lenguaje de clase. Tales cosas son una regresión a mis gustos.

Lonnie Best
fuente
1

OOP para mí significa solo mensajes, retención y protección local y ocultación del proceso estatal, y un enlace tardío extremo de todas las cosas - Alan Kay

Entonces, lo que está diciendo aquí es que OO se trata de hacer cajas negras que respondan a los mensajes. En cierto modo, REST es el último sistema OO en el sentido de que utiliza verbos (es decir, un mensaje) y recursos (es decir, un cuadro opaco que contiene algunos datos).

Entonces, la pregunta de por qué algunos están basados ​​en la clase y otros en el prototipo pierde el punto de que realmente no importa, ambos son meras implementaciones. Un sistema que solo usa mensajes en lugar de llamadas a métodos es tan OO como las dos instancias que menciona.

gbjbaanb
fuente