Pull to refresh

Comments 9

>… так как он использует свойство __proto__, недоступное в некоторых реализациях JS
А почему не замените его на constructor.prototype?

> При таком наследовании теряется гибкость. Простейший пример — при изменении метода предка не меняются методы в наследованных классах.
---Разве классическое наследование предполагает это? По сути, они устроили классическое наследование, а Вы предлагаете превратить его в прототипное. (Если не имеет значения, то прототипное, конечно, экономичнее, но тогда не имеет смысла этот совет: «Всё что нужно — после наследования класса средствами кофе удалить всё унаследованное...»). Зачем удалять, если нужно не писать? Т.е. пишете свою либу полностью без кофейного наследования.)

>С использованием описанных подходов, становится возможным писать модульный
объектно-ориентированный код, не врываясь в глобальное пространство имён.

---С использованием каких подходов это было невозможно?
1. .prototype — будет применяться к экземплярам класса. Если вы про то, чтобы сделать промежуточный класс для создания класса потомка с нужным прототипом, то тоже загвоздка тут. Чтобы этот прототип применился, нужно вызвать new. При этом JS создает объект с таким прототипом, а нужна функция. Все равно придется использовать __proto__.

Если же я неправильно понял, приведите, пожалуйста, пример.

2. Я уже и забывать начал, что где-то нельзя переопределять методы :) Но раз в JS можно переопределять, я этот контекст и использовал. Не уверен, называется ли имеющееся классическим, но в любом случае оно принадлежит подмножеству, доступному с помощью classkit.
2.1. Можно конечно и свою полностью, но так как-то нагляднее и везде одинаково. А где потребуется — там расширять возможности.
Но идея отличная — я добавлю такую функциональность.

3. Тут вы тоже правы — формулировка неправильная. Можно было. Но у каждого свой способ, и это часто мешает совместной разработке. classkit я писал с оглядкой на Ruby, потому что в нём пока лучшая подель модулей и классов, которую я встречал. Изобретать свой велосипед заново и обкатывать его тоже не хотелось.
1. Нет, я про то, чтобы просто везде заменить .__proto__ на .constructor.prototype, т.к. это его определение за малыми исключениями для null и ещё чего-то. Оправдание __proto__ может быть лишь в этих исключениях (или нежелании их обработать :) ), потому и вопрос, что помешало?
К сожалению, Function.protoype (ведь это он и есть SomeClass.constructor.prototype) в моей версии node.js доступен только для чтения. Да и в браузере так же. К нему лишь можно добавлять свойства.
Да и если поменять его сначала для одной функции, а потом для другой, то и в первой он поменяется. А кому нужно наследование, которое наследует во все классы сразу.
А 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
Нет, я никогда не менял прототипы, надобности не было, поэтому и спросил. Для изменения, действительно, «constructor.prototype» не проходит в свойство. Как оказалось, a.constructor !==A. Смотрите:
    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».
Я, наверное, непонятно выразился в предыдущем коментарии. Класс — технически это функция. А у любой функции в js .constructor — Function. A Function.prototype (он же .constructor.prototype для класса) перезаписать нельзя, только изменять. Да и то выходит, что он один на все функции.

Во 2м примере вы привели пример изменения прототипа класса. Это всегда было. Я добивался того, чтобы так же можно было поступать с методами класса (статическими, если так будет понятнее). A.classMethod напримерю. Чтобы в унаследованном В, он был доступен по цепочке прототипов, а не собственным свойством.
CoffeeScript принёс в JS неплохую абстракцию классов, основанную на прототипах.

Учитывая, что она всегда была в JS.
Абстракция? Если точнее, были конструкторы и их прототипы. Кофе поверх этого позволил группировать код относящийся к классу, объявлять методы классов, определять наследование, для которого до этого нужно было было писать функции или подключать библиотеки.
Хм, виноват. Всё таки изначально я неправильно вас понял. Теперь всё понятно.
Sign up to leave a comment.

Articles