I have three coffeescript classes, set up like this:
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.
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.
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. 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?
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 Awould work. This does indeed makeC instanceof BandB instanceof Abecometrue, but it doesn’t copy prototypal properties as desired. So, I’ve rewritten the answer.]Let’s walk through this:
At this point,
C::foois 1 andC::bazis 3. If we then runthat overwrites
C‘s existing prototype with an instance ofB(child.prototype = ...), so onlyC::baris defined.This doesn’t happen when we use the
class X extends Ysyntax because properties are attached toX‘s prototype only after its prototype is overwritten. So, let’s write a wrapper aroundextendsthat saves existing prototype properties, then restores them:Applying this to our example:
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. 🙂