He buscado en Google tantos enlaces y no puedo tener una buena idea sobre la diferencia entre la herencia clásica y la herencia prototípica.
He aprendido algunas cosas de estos, pero todavía estoy confundido acerca de los conceptos.
Herencia clásica
// Shape - superclass
function Shape() {
this.x = 0;
this.y = 0;
}
//superclass method
Shape.prototype.move = function(x, y) {
this.x += x;
this.y += y;
console.info("Shape moved.");
};
// Rectangle - subclass
function Rectangle() {
Shape.call(this); //call super constructor.
}
//subclass extends superclass
Rectangle.prototype = Object.create(Shape.prototype);
¿La herencia clásica utiliza la herencia prototípica en su interior?
http://aaditmshah.github.io/why-prototypal-inheritance-matters/
Desde el enlace anterior, aprendí que no podemos agregar nuevos métodos en tiempo de ejecución en la herencia clásica . ¿Es esto correcto? Pero puede verificar el código anterior. Puedo agregar el método "mover" y cualquier método en tiempo de ejecución a través del prototipo . Entonces, ¿esto es herencia clásica basada en prototipos? Si es así, ¿cuál es la herencia clásica real y la herencia de prototipos? Estoy confundido por eso.
Herencia prototípica.
function Circle(radius) {
this.radius = radius;
}
Circle.prototype.area = function () {
var radius = this.radius;
return Math.PI * radius * radius;
};
Circle.prototype.circumference: function () {
return 2 * Math.PI * this.radius;
};
var circle = new Circle(5);
var circle2 = new Circle(10);
¿Es esto similar a la herencia clásica? Estoy totalmente confundido acerca de qué es la herencia prototípica. ¿Qué es la herencia clásica? ¿Por qué es mala la herencia clásica?
¿Puede darme un ejemplo simple para comprenderlos mejor de una manera simple?
Gracias,
Siva
fuente
Respuestas:
Los dos ejemplos de código que demostró en su pregunta hacen uso de herencia prototípica. De hecho, cualquier código orientado a objetos que escriba en JavaScript es un paradigma de herencia prototípica. JavaScript simplemente no tiene herencia clásica. Esto debería aclarar un poco las cosas:
Como puede ver, la herencia prototípica y la herencia clásica son dos paradigmas diferentes de herencia. Algunos lenguajes como Self, Lua y JavaScript admiten la herencia de prototipos. Sin embargo, la mayoría de lenguajes como C ++, Java y C # admiten la herencia clásica.
Una descripción general rápida de la programación orientada a objetos
Tanto la herencia prototípica como la herencia clásica son paradigmas de programación orientados a objetos (es decir, tratan con objetos). Los objetos son simplemente abstracciones que encapsulan las propiedades de una entidad del mundo real (es decir, representan palabras reales en el programa). Esto se conoce como abstracción.
Abstracción: la representación de cosas del mundo real en programas de computadora.
En teoría, una abstracción se define como "un concepto general formado al extraer características comunes de ejemplos específicos". Sin embargo, por el bien de esta explicación, usaremos la definición antes mencionada.
Ahora bien, algunos objetos tienen muchas cosas en común. Por ejemplo, una moto de barro y una Harley Davidson tienen mucho en común.
Una bici de barro:
Una Harley Davidson:
Una moto de barro y una Harley Davidson son ambas motos. Por lo tanto, una bicicleta es una generalización tanto de una bicicleta de barro como de una Harley Davidson.
En el ejemplo anterior, la moto, la moto de barro y la Harley Davidson son todas abstracciones. Sin embargo, la moto es una abstracción más general de la moto de barro y la Harley Davidson (es decir, tanto la moto de barro como la Harley Davidson son tipos específicos de motos).
Generalización: una abstracción de una abstracción más específica.
En la programación orientada a objetos creamos objetos (que son abstracciones de entidades del mundo real) y usamos clases o prototipos para crear generalizaciones de estos objetos. Las generalizaciones se crean por herencia. Una bicicleta es una generalización de una bicicleta de barro. De ahí que las motos de barro hereden de las bicicletas.
Programación clásica orientada a objetos
En la programación clásica orientada a objetos tenemos dos tipos de abstracciones: clases y objetos. Un objeto, como se mencionó anteriormente, es una abstracción de una entidad del mundo real. Por otro lado, una clase es una abstracción de un objeto u otra clase (es decir, es una generalización). Por ejemplo, considere:
Como puede ver en los lenguajes de programación orientados a objetos clásicos, los objetos son solo abstracciones (es decir, todos los objetos tienen un nivel de abstracción de 1) y las clases son solo generalizaciones (es decir, todas las clases tienen un nivel de abstracción mayor que 1).
Los objetos en los lenguajes de programación orientados a objetos clásicos solo se pueden crear instanciando clases:
En resumen, en los lenguajes de programación orientados a objetos clásicos, los objetos son abstracciones de entidades del mundo real y las clases son generalizaciones (es decir, abstracciones de objetos u otras clases).
Por lo tanto, a medida que aumenta el nivel de abstracción, las entidades se vuelven más generales y a medida que el nivel de abstracción disminuye, las entidades se vuelven más específicas. En este sentido, el nivel de abstracción es análogo a una escala que va desde entidades más específicas hasta entidades más generales.
Programación prototípica orientada a objetos
Los lenguajes de programación orientados a objetos prototípicos son mucho más simples que los lenguajes de programación orientados a objetos clásicos porque en la programación orientada a objetos prototípicos solo tenemos un tipo de abstracción (es decir, objetos). Por ejemplo, considere:
Como puede ver en los lenguajes de programación prototípicos orientados a objetos, los objetos son abstracciones de entidades del mundo real (en cuyo caso simplemente se denominan objetos) u otros objetos (en cuyo caso se denominan prototipos de los objetos que abstraen). Por tanto, un prototipo es una generalización.
Los objetos en lenguajes de programación orientados a objetos prototípicos pueden crearse ex-nihilo (es decir, de la nada) o de otro objeto (que se convierte en el prototipo del objeto recién creado):
En mi humilde opinión, los lenguajes de programación orientados a objetos prototípicos son más poderosos que los lenguajes de programación orientados a objetos clásicos porque:
A estas alturas, debe haberse dado cuenta de la diferencia entre la herencia clásica y la herencia prototípica. La herencia clásica se limita a las clases que heredan de otras clases. Sin embargo, la herencia de prototipos incluye no solo los prototipos que heredan de otros prototipos, sino también los objetos que heredan de los prototipos.
Isomorfismo de clase prototipo
Debes haber notado que los prototipos y las clases son muy similares. Es verdad. Son. De hecho, son tan similares que puedes usar prototipos para modelar clases:
Con la
CLASS
función anterior , puede crear prototipos que parecen clases:Sin embargo, lo contrario no es cierto (es decir, no puede usar clases para modelar prototipos). Esto se debe a que los prototipos son objetos, pero las clases no son objetos. Son un tipo de abstracción completamente diferente.
Conclusión
En resumen, aprendimos que una abstracción es un "concepto general formado al extraer características comunes de ejemplos específicos" y que la generalización es "una abstracción de una abstracción más específica" . También aprendimos sobre las diferencias entre la herencia prototípica y clásica y cómo ambas son dos caras de la misma moneda.
Como nota de despedida, me gustaría comentar que hay dos patrones de herencia prototípica: el patrón prototípico y el patrón constructor. El patrón prototípico es el patrón canónico de herencia prototípica, mientras que el patrón constructor se usa para hacer que la herencia prototípica se parezca más a la herencia clásica. Personalmente prefiero el patrón prototípico.
PD: Soy el tipo que escribió la publicación del blog " Por qué importa la herencia prototípica " y respondió a la pregunta "¿ Beneficios de la herencia prototípica sobre la clásica? ". Mi respuesta es la respuesta aceptada.
fuente
programming with classes = classical inheritance
,programming with prototypes = prototypal inheritance
,programming with constructors = weird form of prototypal inheritance that looks a lot like classical inheritance
. Espero que aclare las cosas.Antes de saltar a la herencia, veremos dos modelos principales para crear instancias (objetos) en javascript:
Modelo clásico: el objeto se crea a partir de un plano (clase)
Modelo prototípico: el objeto se crea directamente a partir de otro objeto.
En cualquier caso, la herencia * se logra vinculando objetos utilizando un objeto prototipo.
(* Los métodos de clase base son accesibles a través de la clase derivada a través del objeto prototipo y no es necesario que estén explícitamente presentes en la clase derivada).
Aquí hay una buena explicación para comprender mejor ( http://www.objectplayground.com/ )
fuente
Un perro es un animal. Suzanna es un perro. En la herencia clásica,
Animal
es una clase,Dog
es una subclase deAnimal
ysuzanna
es una instancia de aDog
.En la herencia prototípica, no hay clase. Tienes un
animal
, que es un objeto. Adog
es otro objeto, que se clona y se extiendeanimal
(el objeto prototipo).suzanna
es un tercer objeto, que copia y extiendedog
.Si escribe en
Dog
lugar dedog
, especialmente si creaDog
algún tipo de función "constructora", entonces no está haciendo herencia prototípica; estás haciendo herencia (pseudo) clásica . El hecho de que esté utilizandoObject.create()
para lograr esto no significa que esté haciendo herencia prototípica.De hecho, JavaScript solo admite la herencia de prototipos. El
new
operador confuso y el.prototype
atributo están ahí para hacer que la herencia prototípica parezca herencia (pseudo) clásica.Douglas Crockford explora esto en profundidad en su libro "JavaScript: The Good Parts".
fuente