我有三个coffeescript类,设置如下: class Aclass C extends Aclass B 这样原型链看起来像这样: A - CB 我需要原型链看起来像这样: A - B - C 问题在于我无法触及A和C的定义. 我想做的是创建一个可
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__魔术,事情并不那么简单.有没有人知道如何注入原型链,这基本上就像你说C类扩展B而B类首先扩展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[更新:我原来回答说C扩展了B; B延伸A会起作用.这确实使C实例B和B实例A变为真,但它不会根据需要复制原型属性.所以,我改写了答案.]
让我们来看看:
class A foo: 1 class B bar: 2 class C extends A baz: 3
此时,C :: foo为1,C :: baz为3.如果我们再运行
C extends B
用B实例(child.prototype = …)覆盖C的现有原型,因此只定义了C :: bar.
当我们使用类X扩展Y语法时不会发生这种情况,因为只有在覆盖原型后才将属性附加到X的原型.那么,让我们编写一个包装器来保存现有的原型属性,然后恢复它们:
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.