[ Обновление: Первоначально я ответил, что C extends B; B extends A
будет работать.Это действительно заставляет C instanceof B
и B instanceof A
становиться true
, но это не копирует свойства прототипа по желанию.Итак, я переписал ответ.]
Давайте пройдемся по этому вопросу:
class A
foo: 1
class B
bar: 2
class C extends A
baz: 3
На этом этапе C::foo
равно 1, а C::baz
равно 3. Если мы запустим
C extends B
, который перезаписывает существующий прототип C
с экземпляром B
(child.prototype = ...
), поэтому определяется только C::bar
.
Этого не происходиткогда мы используем синтаксис class X extends Y
, потому что свойства присоединяются к прототипу X
только после того, как его прототип будет перезаписан.Итак, давайте напишем оболочку вокруг extends
, которая сохраняет существующие свойства прототипа, а затем восстанавливает их:
inherits = (child, parent) ->
proto = child::
child extends parent
child::[x] = proto[x] for own x of proto when x not of child::
child
Применяя это к нашему примеру:
inherits B, A
inherits C, B
console.log new C instanceof B, new B instanceof A # true, true
console.log B::foo, B::bar, B::baz # 1, 2, undefined
console.log C::foo, C::bar, C::baz # 1, 2, 3
Если вы хотитеЧтобы узнать больше о внутренней работе классов CoffeeScript, вы можете проверить мою книгу о CoffeeScript , опубликованную замечательными людьми из PragProg.:)