在coffeescript继承链中注入一个新类

时间:2011-08-26 14:56:41

标签: coffeescript

我有三个coffeescript课程,设置如下:

class A
class C extends A
class B

这样原型链看起来像这样:

A -> C
B

我需要原型链看起来像这样:

A -> B -> C

我不能触及A和C的定义。

我想做的是制作一个可以这样调用的注入函数:

inject B, C

在A之前将B注入C的原型链中,然后将B的原型链设置为注入之前的任何C。

我认为这很简单,比如

C extends (B extends C.prototype)

但不幸的是,由于coffeescript所做的所有原型/ __ super__魔术,事情并不那么简单。有没有人知道如何注入原型链,这基本上就像你先说class C extends Bclass 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 个答案:

答案 0 :(得分:3)

[更新:我原来回答C extends B; B extends A可行。这确实会使C instanceof BB 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

CB)的实例覆盖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类内部工作原理的更多信息,您可能需要查看由PragProg的优秀人员发布的my book on CoffeeScript。 :)