Я поискал в Google так много ссылок и не могу понять разницу между классическим и прототипным наследованием?
Я кое-чему научился из них, но все еще не понимаю концепции.
Классическое наследование
// 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);
Использует ли классическое наследование прототипное наследование внутри?
http://aaditmshah.github.io/why-prototypal-inheritance-matters/
Из приведенной выше ссылки я узнал, что мы не можем добавлять новые методы во время выполнения в классическом наследовании . Это верно? Но вы можете проверить приведенный выше код. Я могу добавить метод «перемещения» и любые методы во время выполнения через прототип . Так это классическое наследование на основе прототипов? Если да, то что на самом деле представляет собой классическое наследование и наследование прототипа? Я смущен этим.
Прототипное наследование.
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);
Это похоже на классическое наследование? Я совершенно не понимаю, что такое прототипное наследование? Что такое классическое наследование? Почему классическое наследование - это плохо?
Не могли бы вы привести мне простой пример, чтобы лучше понять это простым способом.
Спасибо,
Сива
источник
Ответы:
Оба примера кода, которые вы продемонстрировали в своем вопросе, используют прототипное наследование. Фактически любой объектно-ориентированный код, который вы пишете на JavaScript, является парадигмой прототипного наследования. В JavaScript просто нет классического наследования. Это должно немного прояснить ситуацию:
Как видите, прототипное и классическое наследование - это две разные парадигмы наследования. Некоторые языки, такие как Self, Lua и JavaScript, поддерживают прототипное наследование. Однако большинство языков, таких как C ++, Java и C #, поддерживают классическое наследование.
Краткий обзор объектно-ориентированного программирования
И прототипное, и классическое наследование - это парадигмы объектно-ориентированного программирования (т.е. они имеют дело с объектами). Объекты - это просто абстракции, которые инкапсулируют свойства сущности реального мира (т.е. они представляют реальные словесные вещи в программе). Это называется абстракцией.
Абстракция: представление вещей реального мира в компьютерных программах.
Теоретически абстракция определяется как «общее понятие, образованное путем извлечения общих черт из конкретных примеров». Однако для объяснения мы будем использовать вместо этого вышеупомянутое определение.
Теперь у некоторых объектов много общего. Например, грязевой байк и Harley Davidson имеют много общего.
Грязевой байк:
Харлей Дэвидсон:
Грязевой байк и Харлей Дэвидсон - оба мотоцикла. Следовательно, байк - это обобщение как грязевого велосипеда, так и Harley Davidson.
В приведенном выше примере байк, грязевой байк и Harley Davidson - все абстракции. Однако байк - это более общая абстракция от грязевого велосипеда и Harley Davidson (то есть и грязевой байк, и Harley Davidson являются конкретными типами велосипедов).
Обобщение: абстракция более конкретной абстракции.
В объектно-ориентированном программировании мы создаем объекты (которые являются абстракциями сущностей реального мира) и используем классы или прототипы для создания обобщений этих объектов. Обобщения создаются посредством наследования. Велосипед - это обобщение грязевого велосипеда. Следовательно, грязевые велосипеды унаследованы от мотоциклов.
Классическое объектно-ориентированное программирование
В классическом объектно-ориентированном программировании есть два типа абстракций: классы и объекты. Как упоминалось ранее, объект - это абстракция сущности реального мира. С другой стороны, класс - это абстракция объекта или другого класса (т. Е. Это обобщение). Например, рассмотрим:
Как вы можете видеть в классических объектно-ориентированных языках программирования, объекты - это только абстракции (т.е. все объекты имеют уровень абстракции 1), а классы - только обобщения (т.е. все классы имеют уровень абстракции больше 1).
Объекты в классических объектно-ориентированных языках программирования могут быть созданы только путем создания экземпляров классов:
Подводя итог, в классических объектно-ориентированных языках программирования объекты - это абстракции сущностей реального мира, а классы - это обобщения (т. Е. Абстракции объектов или других классов).
Следовательно, по мере увеличения уровня абстракции сущности становятся более общими, а по мере уменьшения уровня абстракции сущности становятся более конкретными. В этом смысле уровень абстракции аналогичен шкале от более конкретных сущностей до более общих.
Прототипное объектно-ориентированное программирование
Прототипные объектно-ориентированные языки программирования намного проще классических объектно-ориентированных языков программирования, потому что в прототипном объектно-ориентированном программировании у нас есть только один тип абстракции (т. Е. Объекты). Например, рассмотрим:
Как вы можете видеть в прототипах объектно-ориентированных языков программирования, объекты являются абстракциями либо сущностей реального мира (в этом случае они просто называются объектами), либо других объектов (в этом случае они называются прототипами тех объектов, которые они абстрагируют). Следовательно, прототип - это обобщение.
Объекты в прототипных объектно-ориентированных языках программирования могут быть созданы либо ex-nihilo (то есть из ничего), либо из другого объекта (который становится прототипом вновь созданного объекта):
По моему скромному мнению, прототипные объектно-ориентированные языки программирования более мощные, чем классические объектно-ориентированные языки программирования, потому что:
К настоящему времени вы, должно быть, осознали разницу между классическим и прототипным наследованием. Классическое наследование ограничено классами, унаследованными от других классов. Однако прототипное наследование включает не только прототипы, унаследованные от других прототипов, но и объекты, унаследованные от прототипов.
Изоморфизм класса прототипа
Вы, наверное, заметили, что прототипы и классы очень похожи. Это правда. Они есть. На самом деле они настолько похожи, что вы можете использовать прототипы для моделирования классов:
Используя указанную выше
CLASS
функцию, вы можете создавать прототипы, похожие на классы:Однако обратное неверно (т.е. вы не можете использовать классы для моделирования прототипов). Это потому, что прототипы являются объектами, а классы - не объектами. Это совершенно другой тип абстракции.
Вывод
Подводя итог, мы узнали, что абстракция - это «общее понятие, образованное путем извлечения общих черт из конкретных примеров», а обобщение - это «абстракция более конкретной абстракции» . Мы также узнали о различиях между прототипным и классическим наследованием и о том, что оба они являются двумя сторонами одной медали.
На прощание я хотел бы отметить, что существует два шаблона прототипного наследования: шаблон прототипа и шаблон конструктора. Шаблон прототипа - это канонический шаблон наследования прототипа, тогда как шаблон конструктора используется для того, чтобы сделать прототипное наследование более похожим на классическое наследование. Лично я предпочитаю прототипный паттерн.
PS Я тот парень, который написал сообщение в блоге « Почему имеет значение прототипное наследование » и ответил на вопрос « Преимущества прототипного наследования перед классическим? ». Мой ответ - принятый ответ.
источник
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
. Надеюсь, что это проясняет ситуацию.Прежде чем перейти к наследованию, мы рассмотрим два основных модели для создания экземпляров (объектов) в javascript:
Классическая модель: объект создается из чертежа (класса)
Прототипная модель: объект создается непосредственно из другого объекта.
В любом случае наследование * достигается путем связывания объектов с помощью объекта-прототипа.
(* методы базового класса доступны через производный класс через объект-прототип и не обязаны явно присутствовать в производном классе.)
Вот хорошее объяснение, чтобы лучше понять ( http://www.objectplayground.com/ )
источник
Собака - это животное. Сюзанна - собака. В классическом наследовании
Animal
- это класс,Dog
является подклассомAnimal
иsuzanna
является экземпляромDog
.В прототипном наследовании нет класса. У вас
animal
есть объект. Adog
- это еще один объект, который клонирует и расширяетanimal
(объект-прототип).suzanna
это третий объект, который копирует и расширяетdog
.Если вы пишете
Dog
вместоdog
, особенно если вы выполняетеDog
какую-то функцию «конструктор», то вы не выполняете прототипное наследование; вы выполняете (псевдо) классическое наследование . Тот факт, что вы используетеObject.create()
для этого, не означает, что вы выполняете прототипное наследование.Фактически, JavaScript поддерживает только прототипное наследование. Запутывающий
new
оператор и.prototype
атрибут используются для того, чтобы прототипное наследование выглядело как (псевдо) классическое наследование.Дуглас Крокфорд подробно исследует это в своей книге «JavaScript: хорошие стороны».
источник