Pesquisei tantos links no Google e não consigo ter uma boa ideia sobre a diferença entre herança clássica e herança prototípica?
Aprendi algumas coisas com eles, mas ainda estou confuso sobre os conceitos.
Herança clássica
// 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);
A herança clássica usa herança prototípica internamente?
http://aaditmshah.github.io/why-prototypal-inheritance-matters/
No link acima, aprendi que não podemos adicionar novos métodos em tempo de execução na herança clássica . Isso está correto? Mas você pode verificar o código acima , posso adicionar o método "mover" e quaisquer métodos em tempo de execução através do protótipo . Portanto, esta é uma herança clássica baseada em protótipo? Em caso afirmativo, o que é herança clássica real e herança de protótipo? Estou confuso com isso.
Herança 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);
Isso é semelhante à herança clássica? Estou totalmente confuso sobre o que é herança prototípica? O que é herança clássica? Por que a herança clássica é ruim?
Você pode me dar um exemplo simples para melhor entendê-los de uma maneira simples.
Obrigado,
Siva
fonte
Respostas:
Ambos os exemplos de código que você demonstrou em sua pergunta fazem uso da herança prototípica. Na verdade, qualquer código orientado a objetos que você escreve em JavaScript é um paradigma de herança prototípica. JavaScript simplesmente não tem herança clássica. Isso deve esclarecer um pouco as coisas:
Como você pode ver, a herança prototípica e a herança clássica são dois paradigmas diferentes de herança. Algumas linguagens como Self, Lua e JavaScript suportam herança prototípica. No entanto, a maioria das linguagens como C ++, Java e C # suportam herança clássica.
Uma rápida visão geral da programação orientada a objetos
Tanto a herança prototípica quanto a herança clássica são paradigmas de programação orientada a objetos (ou seja, eles lidam com objetos). Objetos são simplesmente abstrações que encapsulam as propriedades de uma entidade do mundo real (ou seja, eles representam coisas reais no programa). Isso é conhecido como abstração.
Abstração: A representação de coisas do mundo real em programas de computador.
Teoricamente, uma abstração é definida como "um conceito geral formado pela extração de características comuns de exemplos específicos". No entanto, por causa desta explicação, vamos usar a definição acima mencionada.
Agora, alguns objetos têm muitas coisas em comum. Por exemplo, uma bicicleta de lama e uma Harley Davidson têm muito em comum.
Uma bicicleta de lama:
Uma Harley Davidson:
Uma bicicleta de lama e uma Harley Davidson são duas bicicletas. Portanto, uma bicicleta é uma generalização tanto de uma bicicleta de lama quanto de uma Harley Davidson.
No exemplo acima, a bicicleta, a bicicleta de lama e a Harley Davidson são todas abstrações. No entanto, a bicicleta é uma abstração mais geral da bicicleta de lama e da Harley Davidson (ou seja, a bicicleta de lama e a Harley Davidson são tipos específicos de bicicletas).
Generalização: uma abstração de uma abstração mais específica.
Na programação orientada a objetos, criamos objetos (que são abstrações de entidades do mundo real) e usamos classes ou protótipos para criar generalizações desses objetos. As generalizações são criadas por meio de herança. Uma bicicleta é uma generalização de uma bicicleta de lama. Conseqüentemente, as bicicletas de lama são herdadas das bicicletas.
Programação Clássica Orientada a Objetos
Na programação clássica orientada a objetos, temos dois tipos de abstrações: classes e objetos. Um objeto, como mencionado antes, é uma abstração de uma entidade do mundo real. Por outro lado, uma classe é uma abstração de um objeto ou outra classe (ou seja, é uma generalização). Por exemplo, considere:
Como você pode ver em linguagens de programação orientadas a objetos clássicas, os objetos são apenas abstrações (ou seja, todos os objetos têm um nível de abstração 1) e as classes são apenas generalizações (ou seja, todas as classes têm um nível de abstração maior que 1).
Objetos em linguagens de programação orientadas a objetos clássicas só podem ser criados instanciando classes:
Em suma, nas linguagens de programação orientadas a objetos clássicas, os objetos são abstrações de entidades do mundo real e as classes são generalizações (ou seja, abstrações de objetos ou de outras classes).
Portanto, à medida que o nível de abstração aumenta, as entidades se tornam mais gerais e, à medida que o nível de abstração diminui, as entidades se tornam mais específicas. Nesse sentido, o nível de abstração é análogo a uma escala que varia de entidades mais específicas a entidades mais gerais.
Programação Prototípica Orientada a Objetos
Linguagens de programação orientadas a objetos prototípicas são muito mais simples do que as linguagens de programação orientadas a objetos clássicas porque na programação orientada a objetos prototípica temos apenas um tipo de abstração (ou seja, objetos). Por exemplo, considere:
Como você pode ver em linguagens de programação orientadas a objetos prototípicas, os objetos são abstrações de entidades do mundo real (nesse caso, são simplesmente chamados de objetos) ou de outros objetos (nesse caso, são chamados de protótipos dos objetos que abstraem). Portanto, um protótipo é uma generalização.
Objetos em linguagens de programação orientadas a objetos prototípicas podem ser criados ex-nihilo (ou seja, do nada) ou a partir de outro objeto (que se torna o protótipo do objeto recém-criado):
Na minha humilde opinião, as linguagens de programação orientadas a objetos prototípicas são mais poderosas do que as linguagens de programação orientadas a objetos clássicas porque:
Você já deve ter percebido a diferença entre a herança clássica e a herança prototípica. A herança clássica é limitada a classes que herdam de outras classes. No entanto, a herança prototípica inclui não apenas protótipos herdados de outros protótipos, mas também objetos herdados de protótipos.
Isomorfismo de classe de protótipo
Você deve ter notado que protótipos e classes são muito semelhantes. Isso é verdade. Eles são. Na verdade, eles são tão semelhantes que você pode usar protótipos para modelar classes:
Usando a
CLASS
função acima , você pode criar protótipos que se parecem com classes:No entanto, o inverso não é verdadeiro (ou seja, você não pode usar classes para modelar protótipos). Isso ocorre porque os protótipos são objetos, mas as classes não são objetos. Eles são um tipo totalmente diferente de abstração.
Conclusão
Em suma, aprendemos que uma abstração é um "conceito geral formado pela extração de características comuns de exemplos específicos" e que a generalização é "uma abstração de uma abstração mais específica" . Também aprendemos sobre as diferenças entre herança prototípica e clássica e como ambas são duas faces da mesma moeda.
Em uma nota de despedida, gostaria de observar que existem dois padrões de herança prototípica: o padrão prototípico e o padrão construtor. O padrão prototípico é o padrão canônico de herança prototípica, enquanto o padrão do construtor é usado para fazer a herança prototípica parecer mais com a herança clássica. Pessoalmente, prefiro o padrão prototípico.
PS Sou o cara que escreveu a postagem no blog " Por que a herança prototípica é importante " e respondeu à pergunta " Benefícios da herança prototípica em relação à clássica? ". Minha resposta é a resposta aceita.
fonte
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 isso esclareça as coisas.Antes de pular para a herança, daremos uma olhada em dois modelos principais para criar instâncias (objetos) em javascript:
Modelo clássico: o objeto é criado a partir de um projeto (classe)
Modelo prototípico: o objeto é criado diretamente a partir de outro objeto.
Em ambos os casos, a Herança * é obtida vinculando objetos usando o objeto de protótipo.
(* os métodos da classe base são acessíveis por meio da classe derivada por meio do objeto de protótipo e não precisam estar explicitamente presentes na classe derivada.)
Aqui está uma boa explicação para entender melhor ( http://www.objectplayground.com/ )
fonte
Um cachorro é um animal. Suzanna é uma cachorra. Na herança clássica,
Animal
é uma classe,Dog
é uma subclasse deAnimal
esuzanna
é uma instância de aDog
.Na herança prototípica, não há classe. Você tem um
animal
, que é um objeto. Adog
é outro objeto, que clona e estendeanimal
(o objeto protótipo).suzanna
é um terceiro objeto, que copia e estendedog
.Se você escrever em
Dog
vez dedog
, especialmente se fizerDog
algum tipo de função de "construtor", não estará fazendo herança prototípica; você está fazendo herança (pseudo-) clássica . O fato de você estar usandoObject.create()
para conseguir isso não significa que está fazendo herança prototípica.Na verdade, o JavaScript suporta apenas herança prototípica. O
new
operador e o.prototype
atributo confusos existem para fazer a herança prototípica parecer uma herança (pseudo-) clássica.Douglas Crockford explora isso detalhadamente em seu livro "JavaScript: The Good Parts".
fonte