[英]Injecting a new class into the coffeescript inheritance chain
I have three coffeescript classes, set up like this: 我有三个coffeescript类,设置如下:
class A
class C extends A
class B
so that the prototype chain looks like this: 这样原型链看起来像这样:
A -> C
B
and I need the prototype chain to look like this: 我需要原型链看起来像这样:
A -> B -> C
The catch being that I can't touch the definitions of A and C. 问题在于我无法触及A和C的定义。
What I'd like to do is make an inject function that can be called like this: 我想做的是创建一个可以像这样调用的注入函数:
inject B, C
that injects B into C's prototype chain before A, and then set up B's prototype chain to whatever C's was before the injection. 在A之前将B注入C的原型链中,然后将B的原型链设置为注入之前的任何C。
I thought this would be simple, something like 我认为这很简单,就像
C extends (B extends C.prototype)
But unfortunately, things aren't quite that simple, due to all the prototype/__super__ magic that coffeescript does. 但不幸的是,由于coffeescript所做的所有原型/ __ super__魔术,事情并不那么简单。 Does anyone know how to inject into the prototype chain such that it's basically like you said
class C extends B
and class B extends A
in the first place? 有没有人知道如何注入原型链,这基本上就像你说
class C extends B
而class B extends A
首先class B extends A
?
Many thanks. 非常感谢。
Clarification: The below code DOES NOT WORK, because the properties fail to be copied over. 澄清:以下代码不起作用,因为属性无法复制。
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
[ Update: I originally answered that C extends B; B extends A
[ 更新:我原来回答说
C extends B; B extends A
C extends B; B extends A
would work. C extends B; B extends A
会起作用。 This does indeed make C instanceof B
and B instanceof A
become true
, but it doesn't copy prototypal properties as desired. 这确实使
C instanceof B
和B instanceof A
变为true
,但它不会根据需要复制原型属性。 So, I've rewritten the answer.] 所以,我改写了答案。]
Let's walk through this: 让我们来看看:
class A
foo: 1
class B
bar: 2
class C extends A
baz: 3
At this point, C::foo
is 1 and C::baz
is 3. If we then run 此时,
C::foo
为1, C::baz
为3.如果我们再运行
C extends B
that overwrites C
's existing prototype with an instance of B
( child.prototype = ...
), so only C::bar
is defined. 用
B
的实例( child.prototype = ...
)覆盖C
的现有原型,因此只定义了C::bar
。
This doesn't happen when we use the class X extends Y
syntax because properties are attached to X
's prototype only after its prototype is overwritten. 当我们使用
class X extends Y
语法时,这不会发生,因为属性仅在其原型被覆盖后附加到X
的原型。 So, let's write a wrapper around extends
that saves existing prototype properties, then restores them: 所以,让我们写一个包装周围
extends
,节省了现有的原型属性,然后恢复它们:
inherits = (child, parent) ->
proto = child::
child extends parent
child::[x] = proto[x] for own x of proto when x not of child::
child
Applying this to our example: 将此应用于我们的示例:
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
If you'd like to learn more about the inner workings of CoffeeScript classes, you might want to check out my book on CoffeeScript , published by the fine folks at PragProg. 如果您想了解更多有关CoffeeScript类的内部工作原理的信息,您可能需要查看我的关于CoffeeScript的书 ,该书由PragProg的优秀人员发布。 :)
:)
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.