2008-12-22 12 views
10

Vengo de lenguajes de orientación a objetos de clases y recientemente he estado aprendiendo esos sofisticados lenguajes dinámicos (JavaScript, Python y Lua) y quiero algunos consejos sobre cómo usar OO en esos idiomas. Sería útil conocer las trampas y las deficiencias de dicho enfoque y las ventajas en comparación con OO tradicional.Orientación de objetos basada en prototipos. ¿Lo bueno, lo malo y lo feo?

La noción general que obtuve es que el OO basado en prototipos es básicamente la programación con objetos, pero no hay un estándar sobre cómo usarlos, mientras que en OO normal hay una forma fija predefinida de crear y usar objetos.

En resumen, ¿qué es lo bueno, lo malo y lo feo de este enfoque?

+0

"clases de idiomas de orientación de objetos": ¿puede proporcionar un idioma de ejemplo o dos? "OO tradicional": ¿puede proporcionar un idioma de ejemplo o dos? –

+0

Asumo: prototipo OO - Javascript, OO tradicional - la mayoría de los otros lenguajes OO. Consideraría a Python como OO tradicional (aunque es probable que pueda hacerlo actuar como un prototipo de lenguaje OO si lo desea). – Dan

+0

@ Dan: suposición interesante: el hecho de que no sea obvio significa que el que pregunta debe proporcionar las definiciones o ejemplos. De lo contrario, la pregunta demasiado vaga para responder. –

Respuesta

13

OO basado en prototipos se presta mal a la comprobación de tipo estático, que algunos podrían considerar una cosa mala o fea. OO basado en prototipos tiene tiene una forma estándar de crear objetos nuevos, usted clona y modifica los objetos existentes. También es posible construir fábricas, etc.

Creo que lo que la gente como la mayor parte (el "bueno") es que OO basado en prototipos es muy ligera y flexible , ofreciendo una muy alta relación potencia a peso .

Para consejos sobre cómo usar OO basado en prototipos, un buen lugar para comenzar es el Self paper original en The Power of Simplicity.

0

Bien, antes que nada, el modelo prototipo no es tan diferente en realidad; Smalltalk usa un tipo similar de esquema; la clase es un objeto con los métodos de clases.

Visto desde la clase POV, una clase es realmente la clase de equivalencias de objetos con los mismos datos y todos los mismos métodos; puede ver agregar un método a un prototipo como crear una nueva subclase.

La implementación es simple, pero hace que sea muy difícil hacer una comprobación de tipo efectiva.

7

Para conservar el ancho de banda aquí está el enlace a my answer on "How can I emulate “classes” in JavaScript? (with or without a third-party library)". Contiene referencias adicionales y ejemplos.

La respuesta corta: el corazón de Prototypal de JavaScript OO es la delegación. En este estilo de programación orientada a objetos diferentes objetos de la misma "clase" puede delegar el manejo de métodos y propiedades para el mismo prototipo (por lo general un tercer objeto):

var foo = { 
    property: 42, 
    inc: function(){ 
     ++this.counter; 
    }, 
    dec: function(){ 
     --this.counter; 
    } 
}; 
// Note: foo does not define `counter`. 

Vamos a crear un constructor de objetos con foo como prototipo . Efectivamente, todo lo no manejado será delegado a foo.

var Bar = function(){ 
    this.counter = 0; 
}; 
Bar.prototype = foo; // This is how we set up the delegation. 

// Some people refer to Bar (a constructor function) as "class". 

var bar = new Bar(); 

console.log(bar.counter); // 0 --- Comes from bar itself 
console.log(bar.property); // 42 --- Not defined in bar, comes from foo 

bar.inc(); // Not defined in bar => delegated to foo 
bar.inc(); 
bar.dec(); // Not defined in bar => delegated to foo 
// Note: foo.inc() and foo.dec() are called but this === bar 
// that is why bar is modified, not foo. 

console.log(bar.counter); // 1 --- Comes from bar itself 

Definamos inc() directamente en la barra:

bar.inc = function(){ 
    this.counter = 42; 
}; 

bar.inc(); // Defined in bar => calling it directly. 
      // foo.inc() is not even called. 
console.log(bar.counter); // 42 --- Comes from bar 

Configuración de la cadena de herencia simple:

var Baz = function(){ 
    this.counter = 99; 
}; 
Baz.protype = new Bar(); 

var baz = new Baz(); 

console.log(baz.counter); // 99 
baz.inc(); 
console.log(baz.counter); // 100 

console.log(baz instanceof Baz); // true 
console.log(baz instanceof Bar); // true 
console.log(baz instanceof Object); // true 

aseado, eh?

+0

console.log (bar.prototype); shoudn't que sea: bar.property? –

+0

¡Sí, buena captura! –

1

La herencia clásica es inherentemente defectuosa en términos de flexibilidad, ya que estamos diciendo que "este objeto es de este tipo y no otro". Algunos lenguajes introducen herencia múltiple para aliviar esto, pero la herencia múltiple tiene sus propios inconvenientes, por lo que los beneficios de la composición pura sobre la herencia (que, en un lenguaje estáticamente tipado, es un tiempo de ejecución en lugar de un mecanismo de tiempo de compilación) se vuelven claros.

Tomando el concepto de composición a este nivel "puro", podemos eliminar completamente la herencia clásica junto con el tipado estático. Al componer objetos en tiempo de ejecución y usarlos como planos (el enfoque prototípico), nunca debemos preocuparnos demasiado por los objetos del boxeo a través de la herencia, ni cargarnos con los problemas inherentes a los enfoques de herencia múltiple.

Por lo tanto, prototipal significa un desarrollo mucho más flexible de los módulos.

Por supuesto, otra cosa es decir que es FÁCIL desarrollar sin tipado estático. IMO, no lo es.