Комментарии 9
>… так как он использует свойство __proto__, недоступное в некоторых реализациях JS
А почему не замените его на constructor.prototype?
> При таком наследовании теряется гибкость. Простейший пример — при изменении метода предка не меняются методы в наследованных классах.
---Разве классическое наследование предполагает это? По сути, они устроили классическое наследование, а Вы предлагаете превратить его в прототипное. (Если не имеет значения, то прототипное, конечно, экономичнее, но тогда не имеет смысла этот совет: «Всё что нужно — после наследования класса средствами кофе удалить всё унаследованное...»). Зачем удалять, если нужно не писать? Т.е. пишете свою либу полностью без кофейного наследования.)
>С использованием описанных подходов, становится возможным писать модульный
объектно-ориентированный код, не врываясь в глобальное пространство имён.
---С использованием каких подходов это было невозможно?
А почему не замените его на constructor.prototype?
> При таком наследовании теряется гибкость. Простейший пример — при изменении метода предка не меняются методы в наследованных классах.
---Разве классическое наследование предполагает это? По сути, они устроили классическое наследование, а Вы предлагаете превратить его в прототипное. (Если не имеет значения, то прототипное, конечно, экономичнее, но тогда не имеет смысла этот совет: «Всё что нужно — после наследования класса средствами кофе удалить всё унаследованное...»). Зачем удалять, если нужно не писать? Т.е. пишете свою либу полностью без кофейного наследования.)
>С использованием описанных подходов, становится возможным писать модульный
объектно-ориентированный код, не врываясь в глобальное пространство имён.
---С использованием каких подходов это было невозможно?
0
1.
Если же я неправильно понял, приведите, пожалуйста, пример.
2. Я уже и забывать начал, что где-то нельзя переопределять методы :) Но раз в JS можно переопределять, я этот контекст и использовал. Не уверен, называется ли имеющееся классическим, но в любом случае оно принадлежит подмножеству, доступному с помощью classkit.
2.1. Можно конечно и свою полностью, но так как-то нагляднее и везде одинаково. А где потребуется — там расширять возможности.
Но идея отличная — я добавлю такую функциональность.
3. Тут вы тоже правы — формулировка неправильная. Можно было. Но у каждого свой способ, и это часто мешает совместной разработке. classkit я писал с оглядкой на Ruby, потому что в нём пока лучшая подель модулей и классов, которую я встречал. Изобретать свой велосипед заново и обкатывать его тоже не хотелось.
.prototype
— будет применяться к экземплярам класса. Если вы про то, чтобы сделать промежуточный класс для создания класса потомка с нужным прототипом, то тоже загвоздка тут. Чтобы этот прототип применился, нужно вызвать new. При этом JS создает объект с таким прототипом, а нужна функция. Все равно придется использовать __proto__.Если же я неправильно понял, приведите, пожалуйста, пример.
2. Я уже и забывать начал, что где-то нельзя переопределять методы :) Но раз в JS можно переопределять, я этот контекст и использовал. Не уверен, называется ли имеющееся классическим, но в любом случае оно принадлежит подмножеству, доступному с помощью classkit.
2.1. Можно конечно и свою полностью, но так как-то нагляднее и везде одинаково. А где потребуется — там расширять возможности.
Но идея отличная — я добавлю такую функциональность.
3. Тут вы тоже правы — формулировка неправильная. Можно было. Но у каждого свой способ, и это часто мешает совместной разработке. classkit я писал с оглядкой на Ruby, потому что в нём пока лучшая подель модулей и классов, которую я встречал. Изобретать свой велосипед заново и обкатывать его тоже не хотелось.
+1
1. Нет, я про то, чтобы просто везде заменить .__proto__ на .constructor.prototype, т.к. это его определение за малыми исключениями для null и ещё чего-то. Оправдание __proto__ может быть лишь в этих исключениях (или нежелании их обработать :) ), потому и вопрос, что помешало?
0
К сожалению, Function.protoype (ведь это он и есть SomeClass.constructor.prototype) в моей версии node.js доступен только для чтения. Да и в браузере так же. К нему лишь можно добавлять свойства.
Да и если поменять его сначала для одной функции, а потом для другой, то и в первой он поменяется. А кому нужно наследование, которое наследует во все классы сразу.
А extendsWithProto как раз таки добавляет предка только в качестве прототипа одного класса.
Если вы правда знаете, как реализовать для всех движков, поделитесь, пожалуйста. Я буду очень благодарен.
Я добавлю еще один пример работы classkit, если может остались вопросы по его функциям.
Да и если поменять его сначала для одной функции, а потом для другой, то и в первой он поменяется. А кому нужно наследование, которое наследует во все классы сразу.
А extendsWithProto как раз таки добавляет предка только в качестве прототипа одного класса.
Если вы правда знаете, как реализовать для всех движков, поделитесь, пожалуйста. Я буду очень благодарен.
Я добавлю еще один пример работы classkit, если может остались вопросы по его функциям.
describe 'coffee_classkit', ->
describe '#extendsWithProto', ->
beforeEach ->
class @A
@x = -> true
class @B extends @A
classkit.extendsWithProto @
it 'keeps child`s own properties clean', ->
assert.deepEqual Object.keys(@A), ['x']
assert.deepEqual Object.keys(@B), ['__super__']
assert.equal @A.x(), true
assert.equal @B.x(), true
0
Нет, я никогда не менял прототипы, надобности не было, поэтому и спросил. Для изменения, действительно, «constructor.prototype» не проходит в свойство. Как оказалось, a.constructor !==A. Смотрите:
Но если обращаться напрямую к родителям (ссылками или цепочками по superclass при наследовании классов), то свойства предков нормально меняются:
Поэтому добраться всегда можно без __proto__, если есть такая задача. Хотя да, будут некрасивые лишние оболочки, делающие аналог __proto__.
В частности, при наследовании конструкторов мы явно прописываем constructor, и тогда схема работает через «constructor.prototype».
A = function(){
this.aa = 'aaAProp';
};
A.prototype = {
bb: 'bbAproto'
};
a = new A();
a.constructor.prototype.bb = 'a-changeProto';
alert(a.constructor.prototype.bb) //a-changeProto - прототип (неизвестно чего) запоминается
alert(a.bb) //bbAproto - но не распространяется
Но если обращаться напрямую к родителям (ссылками или цепочками по superclass при наследовании классов), то свойства предков нормально меняются:
A.prototype.bb = 'new-bbAproto';
alert(a.bb) //new-bbAproto
Поэтому добраться всегда можно без __proto__, если есть такая задача. Хотя да, будут некрасивые лишние оболочки, делающие аналог __proto__.
В частности, при наследовании конструкторов мы явно прописываем constructor, и тогда схема работает через «constructor.prototype».
0
Я, наверное, непонятно выразился в предыдущем коментарии. Класс — технически это функция. А у любой функции в js .constructor — Function. A Function.prototype (он же .constructor.prototype для класса) перезаписать нельзя, только изменять. Да и то выходит, что он один на все функции.
Во 2м примере вы привели пример изменения прототипа класса. Это всегда было. Я добивался того, чтобы так же можно было поступать с методами класса (статическими, если так будет понятнее). A.classMethod напримерю. Чтобы в унаследованном В, он был доступен по цепочке прототипов, а не собственным свойством.
Во 2м примере вы привели пример изменения прототипа класса. Это всегда было. Я добивался того, чтобы так же можно было поступать с методами класса (статическими, если так будет понятнее). A.classMethod напримерю. Чтобы в унаследованном В, он был доступен по цепочке прототипов, а не собственным свойством.
0
CoffeeScript принёс в JS неплохую абстракцию классов, основанную на прототипах.
Учитывая, что она всегда была в JS.
0
Абстракция? Если точнее, были конструкторы и их прототипы. Кофе поверх этого позволил группировать код относящийся к классу, объявлять методы классов, определять наследование, для которого до этого нужно было было писать функции или подключать библиотеки.
0
Зарегистрируйтесь на Хабре, чтобы оставить комментарий
Улучшенное наследование в CoffeeScript