Calling coffescript super methods - coffeescript

I have the following code:
class Animal
constructor: (#name) ->
say: () -> console.log "Hello from animal called #{ #name }"
class Dog extends Animal
say: () ->
super.say()
console.log "Hello from dog called #{ #name }"
a = new Animal('Bobby')
a.say()
d = new Dog("Duffy")
d.say()
The result is not
Hello from animal called Bobby
Hello from animal called Duffy
Hello from dog called Duffy
But I get the following error:
Hello from animal called Bobby
Hello from animal called Duffy
Uncaught TypeError: Cannot call method 'say' of undefined
How come super is undefined? How to call a parent method in order to extend it? Thanks

I found the answer myself, it should be:
class Dog extends Animal
say: () ->
super
console.log "Hello from dog called #{ #name }"

Related

inheritance example from typescript manual

Reading example from typescript manual:
class Animal {
name:string;
constructor(theName: string) { this.name = theName; }
move(meters: number = 0) {
alert(this.name + " moved " + meters + "m.");
}
}
class Snake extends Animal {
constructor(name: string) { super(name); }
move(meters = 5) {
alert("Slithering...");
super.move(meters);
}
}
class Horse extends Animal {
constructor(name: string) { super(name); }
move(meters = 45) {
alert("Galloping...");
super.move(meters);
}
}
var sam = new Snake("Sammy the Python");
var tom: Animal = new Horse("Tommy the Palomino");
sam.move();
tom.move(34);
The question is about the line var tom: Animal = new Horse("Tommy the Palomino");:
As I understand tom is an Animal with properties of a Horse. Is that right?
What is the point to make it this way? Not to declare as var tom: Horse = ...?
Having just one version to give him a chance to degrade/change/evolve to a Snake or any other Animal. Am I right?
...or maybe it is just a typo?
In the example above, Animal is a superclass (also called base class or parent class) of both Horse and Snake. Correspondingly, Horse and Snake are subclasses (derived classes) of Animal.
When you declare the subclasses:
class Snake extends Animal
...
class Horse extends Animal
You're telling the compiler that any every Snake and every Horse is in fact, an Animal as well. This makes Animal the broader category in the "world" of the program. Snake and Horse will inherit the properties of Animal, but they can change them (and/or add a few of their own) to be more specialized.
tom's declaration tells the compiler that the variable will accept any Animal. As we saw earlier, a Horse is an Animal, so the compiler lets it pass.
Hence, they're illustrating the fact that whenever a member of the superclass is expected in any expression, one member of any of its subclasses is acceptable. This is called covariance.
In the most literal sense, there is no evolving or devolving. The line
tom: Animal = new Horse("Tommy the Palomino");
first causes a new Horse object to be created. The object is then assigned to the variable tom, but this assignment does not change the properties of the object. If you ran the example, you'd see that the call horse.move() actually calls the Horse version of the method move, which would report that "Tommy the Palomino moved 45m".
The only discernible side effect of assigning a Horse to an Animal is that the variable, being of the most general type, wouldn't know of any specialized properties of Horse. It only knows what all Animals have in common. Let's say Horse was declared like this:
class Horse extends Animal {
constructor(name: string) { super(name); }
move(meters = 45) {
//...
}
swat_fly() { /* ... */ }
}
You wouldn't be able to call tom.swat_fly(). If you wanted to, you either need to typecast tom (like this: (<Horse>tom).swat_fly()) or declare it as a Horse instead of as an Animal. But I reiterate: the object's properties are not changed to the superclass's.
So no, it's not a typo :)

Calling a method of a super class through extended class leads into TypeError

I'm not sure if the title says it all.
What I'm trying to do is to have a super class (or a more or less abstract class) which then is used by another class which is extending itself from the super class.
Now what I did was to create a simple script:
class Animal
constructor: (#name, #sound) ->
setSound: (#sound) ->
sound: ->
alert "#{#sound}!!!"
name: ->
alert "#{#name}"
class Dog extends Animal
constructor: (#name) ->
#setSound "Woof"
doggy = new Dog "Max"
doggy.sound()
As you can see - this is just a crappy example but what happens is, when I now call doggy.sound() I get an TypeError in return.
You can see this script in action here: http://jsfiddle.net/zrVZb/1/
Am I doing something wrong or is this even a bug in coffeescript?
edit: I just saw, that it is contructor and not construct. But now I'm getting the TypeError instead.
Thanks
Your method is called sound. But then you pass an attribute with the same name, which overwrites this method. Try renaming your sound method into makeSound :
http://jsfiddle.net/V7Dx8/1/

How to define properties to multiple CoffeeScript classes

I want to define multiple properties of different "classes"/prototypes when creating a new object.
class Animal
constructor: (#name, #temperament, #diet) ->
#methods that use those properties
eat: (food) ->
console.log "#{name} eats the #{food}."
class Bird extends Animal
constructor: (#wingSpan) ->
#methods relating only to birds
class Cat extends Animal
constructor: (#tailLength) ->
#methods relating only to cats
myCat = new Cat ("long", {"Mr. Whiskers", "Lazy", "Carnivore"})
I'm doing something wrong, though. Only the constructor for Cat seems to get any properties.
Also, is there a way to define them with key/value pairs?
Ideally, I'd write something like myCat = new Cat (tailLength: "long", name: "Mr. Whiskers", temperament: "Lazy"), so that I can define properties that aren't in order and it would fall back to a default if I failed to define a property like "diet".
My understanding is that prototype methods will bubble up, so if I call myCat.eat 'cat food', the output should be "Mr. Whiskers eats the cat food." But... it can't be since the Animal class isn't getting the new Cat's name.
Just use {} if you mean "an object".
class Animal
constructor: ({#name, #temperament, #diet}) ->
#methods that use those properties
eat: (food) ->
console.log "#{#name} eats the #{food}."
class Bird extends Animal
constructor: ({#wingSpan}) ->
super
#methods relating only to birds
class Cat extends Animal
constructor: ({#tailLength}) ->
super
#methods relating only to cats
myCat = new Cat(tailLength: "long", name: "Mr. Whiskers", temperament: "Lazy", diet: "Carnivore")

Getting to class variable from instance of Class in CoffeeScript

I have a class like this:
class Cow
#feet : 4
constructor: (#name) ->
bes = new Cow "Bessie"
The question is, is it possible to access feet only given bes?
You can use the JavaScript constructor property to get at the class and there you will find your feet:
class Cow
#feet: 4
constructor: (#name) ->
class HexaCow extends Cow
#feet: 6
bes = new Cow('Bessie')
pan = new HexaCow('Pancakes')
alert(bes.constructor.feet) # 4
alert(pan.constructor.feet) # 6
​
Demo: http://jsfiddle.net/ambiguous/ZfsqP/
I don't know of any special CoffeeScript replacement for constructor though.

Get class type in CoffeeScript

How can I find that class of an object once it has been instantiated?
class Cat
constructor: (#name) ->
class Dog
constructor: (#name) ->
cat = new Cat "Kitty"
dog = new Dog "Doggy"
if (cat == Cat) <- I want to do something like this
Just change the == to instanceof
if(cat instanceof Cat)
If you wanted to know the type name of a particular object (which is what I was just looking for when I found this question), you can use the syntax {object}.constructor.name
for example
class Cat
constructor: (#name) ->
class Dog
constructor: (#name) ->
cat = new Cat()
dog = new Dog()
console.log cat.constructor.name
console.log dog.constructor.name
which will output
Cat
Dog
The way to do this is to check the type of an object using either
instanceof
or
typeof
i.e.
if (obj instanceof Awesomeness){
//doSomethingCrazy();
}
Just as in JavaScript, Coffee Script does not provide any abstraction over these functions
AFAIU, the general solution would be using #constructor - Useful when you don't know or don't want to specify the class name.
There was even a discussion regarding making ## a shortcut for it.