2011-06-07 17 views
15

Todos parecen estar de acuerdo en general en que la herencia de prototipos es más simple y más flexible que la herencia de clases. Lo que no he visto en la literatura que he leído es que hay muchos ejemplos de cosas que puedes hacer con herencia de prototipos que no puedes con clásicos. Así que planteo una pregunta simple:¿Qué patrones puedes usar con la herencia de prototipos que no puedes con la clase?

¿Cuáles son algunos patrones que puede usar con la herencia de prototipos que no puede con la herencia de clase y cuál es la orientación que le daría hasta cuándo/si usarlo?

+0

Esto probablemente debería moverse a programmers.stackexchange. –

+1

@Paul: ¿Por qué? Esta no es una pregunta de orientación empresarial/buenas prácticas, más teórica. Al menos, así es como lo leo. –

+0

¿No es eso de lo que se tratan los programadores? SO es sobre ayuda, los programadores se trata de cosas teóricas (entre otras cosas). –

Respuesta

1

Ok, voy a añadir uno, utilice el hecho de que los enlaces son en vivo prototipo a métodos mono-parche para toda una clase de objetos:

var Cat = function(catName) { 
    this.catName = catName; 
}; 
Cat.prototype.meow = function() { 
    console.log(this.catName+" says meow"); 
} 
var mittens = new Cat("Mittens"); 
var whiskers = new Cat("Whiskers"); 
mittens.meow(); // "Mittens says meow" 
whiskers.meow(); // "Whiskers says meow" 

// All cats are now angry 
Cat.prototype.meow = function() { 
    console.log(this.catName+" says hissssss"); 
} 
mittens.meow(); // "Mittens says hissssss" 
whiskers.meow(); // "Whiskers says hissssss" 

Esto sería útil si tiene objetos que de repente necesitan para comenzar a actuar de una manera completamente diferente pero consistente en respuesta a algún tipo de evento global. Tal vez algo como:

  • Temas y despellejar
  • si una página está funcionando en modo "en línea" o "modo offline" (mientras está en línea todas las consultas se almacenan/recuperada a través de AJAX, mientras que las consultas fuera de línea redirigen al navegador almacenamiento)
+1

Solo estoy pidiendo por ignorancia, pero ¿no obtienes este beneficio porque la definición se busca en tiempo de ejecución? Quiero decir, podrías hacer esto con la herencia de clase si también pudieras buscar/cambiar la definición del método en tiempo de ejecución, ¿verdad? –

+1

Sí, esto tiene mucho más que ver con los lenguajes dinámicos que con el prototipado. Python, Ruby, Smalltalk y otros pueden hacer todo lo anterior. – Jordan

+0

@Esteban: Correcto. Java y la mayoría de los otros lenguajes de OO antiguos provienen de un momento en que la búsqueda era costosa, por lo que los tipos son inmutables. La mayoría de los lenguajes de scripting modernos tienen tipos dinámicos. JavaScript y Python incluso permiten agregar métodos a instancias, por lo que cada instancia obtiene sus propios métodos. –

0

Dado que no existe una herencia de clase real en JavaScript, probablemente nunca encontrará literatura que explique lo que no puede hacer con la herencia de clase clásica en JavaScript, a menos que la compare con la herencia de clase en otros idiomas.

Así que voy a considerar su pregunta como si nos referimos:

¿Cuáles son algunos patrones que se pueden utilizar con JavaScript herencia de prototipo que no se puede hacer con la herencia de clases en las lenguas que lo apoyan?

R = En la mayoría de los idiomas generales, orientados a objetos que se basan en la clase de herencia producir objetos que tienen una estructura rígida, que siempre tendrán los mismos métodos y propiedades durante su vida y todos los objetos de las mismas clases se tener la misma estructura

Así que, en general, los patrones se pueden aplicar con un lenguaje basado en prototipos que no puede ser implementado con un lenguaje de herencia de clases son los que dependen de:

  • Añadir o eliminar métodos o propiedades a objetos, sobre la marcha

* Esto se admite muy bien en JavaScript debido a su naturaleza dinámica de colaboración entre dominios. A veces necesita cargar scripts externos desde otros sitios web, pero necesita agregar nuevas funcionalidades sin poder cambiar el código fuente de estas bibliotecas externas.

+0

Ahora que lo pienso, ¿hay algún idioma que tenga un buen soporte para * ambos * tipos de herencia? – MatrixFrog

+1

Sí. Al menos PHP, hazlo con una técnica llamada [sobrecarga] (http://php.net/manual/en/language.oop5.overloading.php). Por supuesto, PHP no es tan dinámico como JavaScript, pero es un ejemplo real del lenguaje de herencia de clases con algún tipo de comportamiento que solo se encuentra en el lenguaje de prototipos. – marcio

2

Una diferencia (tal vez al menos conceptualmente) es que la herencia de clase implica que el hijo ES-A del tipo del padre. La herencia del prototipo no implica tal implicación; un mamífero es un prototipo para un gato (la definición de Merriam-Webster dice que esto significa que es un "patrón para"), pero nada más. Un gato es libre de quitar/agregar/cambiar comportamientos como lo considere oportuno.

+0

En realidad, es incorrecto decir que la herencia de clase implica un "is-a", creo que escuché por primera vez esto explicado por Bob Martin durante un episodio de Herding Code. Un cuadrado "es un" Rectángulo pero cuadrado: el rectángulo rompe el Principio de sustitución de Liskov, ya que cambiar la altura cambiará el ancho y este comportamiento no es el esperado si está trabajando con un rectángulo. Creo que he escuchado que la terminología 'es-a' es una metáfora que gotea de algún proyecto en la comunidad de IA de los años 70.http://www.objectmentor.com/resources/articles/lsp.pdf –

0

No creo que esté de acuerdo con su premisa, pero el principal beneficio de la herencia basada en prototipos es que permite la asignación de propiedades y métodos en tiempo de ejecución a todos los miembros de la clase, incluso cuando ya existen instancias de esa clase.

El teórico en mí realmente se encoge de algunas de esas implicaciones. Imagina depurar algo donde no tienes idea qué parte del código ha redefinido completamente tu estructura de clase. Es más que desalentador.

embargo, he de decir, que ha demostrado ser útil:

Una vez, cuando estaba trabajando en ActionScript 2 (no para los débiles de corazón, ya que es casi un lenguaje no determinista) en el interior de un ActionScript 3 contenedores. Un efecto secundario desconocido de este problema es que elimina la idea de los niveles de memoria (algo esencial para el código heredado de mi empresa). Pude agregar la línea: MovieClip.prototype._level0 = _root; y resolvió el problema.

Para contrarrestar mi argumento anterior, el hecho de que puede modificar todas las instancias después del hecho le proporciona cierta cantidad de energía en situaciones donde no tiene acceso a la base de código original (como en el ejemplo), pero No veo un gran beneficio más allá de eso.

+0

Creo que su queja condena todos los lenguajes dinámicos con fuertes capacidades de metaprogramación. Ruby, Python, etc. Realmente no puedo decir que he tenido una tremenda cantidad de dificultad para depurarlos (o JS para el caso, siempre y cuando haya un banco de pruebas) –

Cuestiones relacionadas