Внедрение нового класса в цепочку наследования coffeescript - PullRequest
4 голосов
/ 26 августа 2011

У меня есть три класса coffeescript, настроенных так:

class A
class C extends A
class B

, чтобы цепочка прототипов выглядела так:

A -> C
B

и мне нужна цепочка прототипов, чтобы она выглядела какthis:

A -> B -> C

Суть в том, что я не могу коснуться определений A и C.

Что я хотел бы сделать, это сделать функцию инъекции, которая может быть вызвана какthis:

inject B, C

, который вводит B в цепочку прототипов C до A, а затем настраивает цепочку прототипов B на то, что было C до инъекции.

Я думал, что это будет просто, что-токак

C extends (B extends C.prototype)

Но, к сожалению, все не так просто, из-за всей магии прототипа / __ super__, которую делает coffeescript.Кто-нибудь знает, как внедрить в цепочку прототипов так, чтобы это в основном, как вы сказали class C extends B и class B extends A в первую очередь?

Большое спасибо.

Разъяснение: приведенный ниже код ДАЕТНЕ РАБОТАЕТ, потому что свойства не могут быть скопированы.

class A
  foo: 1
class B
  bar: 2
class C extends A
  baz: 3

B extends A
C extends B

c = new C
console.log c.foo
console.log c.bar
console.log c.baz

1 Ответ

3 голосов
/ 27 августа 2011

[ Обновление: Первоначально я ответил, что 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.:)

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...