Вопрос о наследовании
Изучаю js, пытаюсь понять наследование.
function Product(name) {
this.name = name;
}
Product.prototype = {
getName: function() {
return this.name;
}
}
function Apple(name) {
Product.call(this, name);
}
extend(Apple.prototype, Product.prototype);
function extend(child, parent) {
for (var i in parent) {
child[i] = parent[i];
}
}
var apple = new Apple("яблоко");
console.log(apple.getName());
Что плохого в использовании extend? То, что это копирование метода из одного прототипа в другой? То есть скопированный метод getName будет ссылаться не на Product.prototype, а на Apple.prototype? В этом проблема или в чём? Поясните, плз. |
Проблема в том, что это копирование, а не наследование. Это разные вещи. Если в Apple.prototype и Product.prototype будут одноименные методы, копирование перезапишет метод ребенка методом предка, наследование - нет. Наследование реализуется так:
function extend(Child, Parent) {
Child.prototype = Object.create(Parent.prototype, {
constructor: {
value: Child,
enumerable: false,
writable: true,
configurable: true
}
});
};
То есть, в итоге должно получиться, что (new Child()).__proto__.__proto__ == (new Parent()).__proto__ |
Твой вариант будет работать, но он кривой:) надо хотя бы так
function Product() {}
Product.prototype = {
getName: function() {
return this.name;
}
}
function Apple(name) {
this.name=name
}
Apple.prototype=Object.create(Product.prototype)
var apple = new Apple("apple");
alert(apple.getName());
Но лучше восстановить связи:
function Product() {}
Product.prototype.getName=function() {
return this.name;
}
function Apple(name) {
this.name=name
}
Apple.prototype=Object.create(Product.prototype)
Apple.prototype.constructor=Apple
var apple = new Apple("apple");
alert(apple.getName())
alert(apple.constructor);
Тут, собчтвенно, класс product вообще не нужен. Ну ладно, пусть будет:) По сабжу. В копировании плохо то, что оно засирает память, и, в некотором смысле, нарушает модульность. |
krutoy,
Опять забыл восстановить ребенку ссылку на его конструктор. Ну и вариант от Erolast ничем не кривой. Еще в копировании плохо то что мы не сможем проверять принадлежность к классу через instaceof |
Цитата:
|
tsigel,
Кстати, вариант того клоуна тоже крив, потому что он избыточен. Вся эта параша, которую он подает вторым параметром Object.create -- не нужна. А пишет эту всю парашу поциэнт, потому что он джаваскрипт не понимает, а этот говнопаттерн где-то увидел и копирует бездумно. Из песни слов не выкинешь, боится клоун, что-то изменить, боится, что-нибудь сломается в коде.:) |
То есть выходит, что все экземпляры "класса" Apple будут иметь свой личный метод getName, в то время как если наследовать через прототип все экземпляры будут ссылаться на один и тот же прототип . Теперь стало понятно. Спасибо всем
|
krutoy,
Вторым аргументом он восстанавливает ссылку на конструктор. |
javacrypt,
Кстати, можно и изящней написать, с сахарком:)
function Product() {}
Object.defineProperty(Product.prototype, "name", {get: function(){return this.name_}})
function Apple(name) {
this.name_=name
}
Apple.prototype=Object.create(Product.prototype)
Apple.prototype.constructor=Apple
var apple = new Apple("apple");
alert(apple.name)
|
Цитата:
Apple.prototype.constructor=Apple А он написал невнятную, нечитаемую, и непонятно зачем нужную парашу. |
krutoy,
Он написал код описаный в стандартах и спецификациях языка. Конечно дескрипторы мало имеют аналогов в других языках программирования и в связи с этим многие их не любят. Но люди которые позиционируют себя как JavaScript программисты должны знать о них и для них эта конструкция будет вполне понятна, лаконична и обычна. |
Цитата:
Apple=function(name){
this.name=name
this.getName=function(){...}
}
А так -- он был бы вс равно общий, разница в том, наследуется ли он от своего класса, или от суперкласса. |
tsigel,
Я не имею ничего против дескрипторов, только там, где они нужны. А где не нужны -- там не нужны, все просто. Он преопределят то, что и так уже есть, это тупость. |
Цитата:
Цитата:
|
Цитата:
|
javacrypt,
В твоем коде, как-бы предполагается, что метод getName, будут иметь не только экзмпляры класса Аpple, но и экземземпляры классов Grape, Cherry, Cranberies и тп |
Перефразирую себя:
выходит, что все экземпляры "класса" Apple будут дублировать метод getName у себя в прототипе, вместо того, что брать его по ссылке из Product.prototype? Так? Класс Product - абстрактный, у него не будет экземпляров. Все категории продуктов будут иметь общие методы унаследованные от него. |
Цитата:
Цитата:
|
Цитата:
Цитата:
|
javacrypt,
Тот дегенерат, который отписался выше, слабо представляет какой понос он выблевывает. Естественно, в js ничего вообще не копируетя, все создается и наполняется ссылками. Но это н значит, что объект с тысячью ссылок весит столько же, сколько пустой объект. А если бы было так, LOL, программы на JS вобще не потребляли бы память, на*й она нужна, ведь все что у нас есть -- объекты со ссылками. Зацени масштаб бредятины, ты в желтом доме такого не услышишь, цени момент:) |
Теперь я кажется понял. Совсем забыл про ссылки на объекты в js. Спасибо. Я вас понял обоих.
|
Erolast, krutoy,
1. мне надо вызвать конструктор родительского класса - как? 2. мне надо вызвать супер метод - как? :) |
nerv_,
В чем проблема? Ты не можешь вызвать функцию? проще всего так
function Super(){alert("Hello!")}
function F(){}
F.prototype=Object.create(Super.prototype)
F.prototype.constructor=F
o=new F
o.__proto__.__proto__.constructor()
я думаю. |
Цитата:
childObject.supermethod() |
Цитата:
|
Цитата:
function Super(){alert("Hello!")}
Super.prototype.onceAgain=function(){alert("Hello again!!!")}
function F(){}
F.prototype=Object.create(Super.prototype)
F.prototype.constructor=F
F.prototype.onceAgain=function(){alert(2)}
o=new F
o.onceAgain=function(){alert(1)}
o.onceAgain()
o.__proto__.onceAgain()
o.constructor.prototype.onceAgain()
o.__proto__.__proto__.onceAgain()
o.__proto__.__proto__.constructor.prototype.onceAgain()
|
Цитата:
|
Erolast, за неимением ES6 в браузере, тебе не кажется, что будет логичным всегда устанавливать ссылку на супер-класс?
Давайте не будем изобретать велосипедов, а просто использовать node.js inherits, благо она кросс-платформенная (клиент/сервер). http://javascript.ru/forum/misc/5188...tml#post342727 krutoy, то, что ты пишешь, вообще ад :) |
|
| Часовой пояс GMT +3, время: 05:25. |