Injecting a new class into the coffeescript inheritance chain - coffeescript

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 A would work. This does indeed make C instanceof B and B instanceof A become true, but it doesn't copy prototypal properties as desired. 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 extends B
that overwrites C's existing prototype with an instance of B (child.prototype = ...), so only C::bar is defined.
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. So, let's write a wrapper around extends that saves existing prototype properties, then restores them:
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. :)

Related

Scala Nested Object Serialization

Hi I have a case class A which contains variables pointing to another class B (with companion object, which has variables pointing to yet another class C which also has companion object). class B and C are from other libraries. What is the easier way that I could serialize my case class A?
case class A() {
val b = B
}
//B & C are defined in a library that I have no control of
object B {
val c = C
}
class B{
...
}
object C{
...
}
class C{
...
}
If these classes are already Serializable, you don't need to do anything special, so the rest of the answer assumes they aren't.
If these fields can be reconstructed from others, mark them as #transient and implement readObject (as described in http://docs.oracle.com/javase/8/docs/api/java/io/Serializable.html) to restore them. Unfortunately, you can't initialize vals in readObject and will have to write something like
case class A() {
private var _b = B
def b = _b
}
If they can't, you need to store something they can be restored from in writeObject as well.
Finally, you can use one of the third-party serialization libraries like Kryo or Scala Pickling, because basically all of them allow to add support for types not under your control (otherwise they couldn't work with the types in standard Java library!)

why self-type class can declare class

I know Scala can only mixin traits, it makes sense for dependency injection and cake pattern. My question is why I can still declare a class which need another "class" but not trait.
Code:
class C
class D { self : C =>}
This is still complied successfully. I thought it should failed compiled, because at this point how can new instance D (C is class not trait).
Edit:
when try to instantiate D:
new D with C //compilation fail class C needs to be a trait to be mixed in.
You should explicitly make class D to extends C as follows:
class C
class D extends C { self: C => }
Furthermore, you can refer to the post Does a class with a self type of another class make sense?, which explains this problem clearly.

How to call foo() function from class A

class A(object):
def foo(self):
print 'A'
class B(A):
def foo(self):
print 'B'
class C(B):
pass
c = C()
c.foo()
>>> B
I want to call the foo() method of class A. So how can I call this foo() method so that it will print 'A'
To directly answer your question, you could define C like this:
class C(B):
def foo(self):
A.foo(self)
However, a better question might be: why are you trying to do this? A class needing to access functions from the, erm, "grandparent" that were also defined in the parent class is a pretty good sign that your inheritance model is not ideal. For example: does C need anything from B; could it inherit directly from A?

coffeescript how to set binding" to a child class in a callback function defined in parent class

I'd like to changing the binding of the callback function in a child class so that the following code indicates 20, rather than 10:
class A
#in = 10
#b: =>
alert(#in)
class B extends A
#in = 20
#w: ->
window.setTimeout(#b,500)
B.w()
If I 'thin-arrow' the definition of A.b, then the binding is to the timeout calling function so #in is undefined. When I fat-arrow it, it binds to the parent class A. I would like it to bind to the child class B, without redefining the method in the child class.
Thanks
I think the best you can do is force the appropriate binding manually when you set up your setTimeout call. Drop the => when defining #b in A:
class A
#...
#b: -> alert(#in)
And then set the binding in B when you call setTimeout:
class B extends A
#...
#w: ->
f = => #b()
window.setTimeout(f, 500)
I think that's as close as you can get using CoffeeScript's pseudo-class-methods.
Demo: http://jsfiddle.net/ambiguous/Y6S8D/

Seamless weaving of trait

I would like to automatically weave the definition of a new function say introduced by an extending trait Ext into an abstract class A:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait A extends super.A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B
b.say
}
However, I obtain the following error:
<console>:12: error: value say is not a member of Test.B
b.say
Any way of doing it?
It seems you are trying to use virtual classes, which is a feature not available in Scala.
Once A and B are defined they can't be redefined (like method overriding).
abstract class A
class B extends A
On the other hand, given your example, your objective could be achieved by a simple mixin. Here it is with few rewrites:
class Base {
abstract class A
class B extends A
case class C extends A
}
trait Ext extends Base {
trait CanSay extends A {
def say = "hello"
}
}
object Test extends Base with Ext {
val b = new B with CanSay
def apply = b.say
}
Test.apply
No sure it will really help, but at least will help you understand what is going on.
Okay, as I said in a comment, it's not entirely clear what you're trying to do here, so I can't really try to suggest ways to do it. However, the approach you're using at the moment will not work.
Consider the class Hierarchy in this situation. At the base, we have A, which is then subclassed with B (in Base) and with Ext.A. These are not related save by their shared supertype, so you'll never find a say method on an instance of B.
The confusion possibly arises through the use of the word abstract. An abstract modifier on a class (even an inner class) does not make it an abstract member of the parent class, but denotes that it itself may have abstract members. There are ways of giving a class an abstract class member - through type parameters or type members. Unfortunately, you cannot derive from these AFAIK.