Classes in CoffeeScript
The Parent Class
We’ll do this mostly by example, since it should be fairly easy for those who have read my introductory article on coffeescript to pick up on what’s happening.
class Bourgeoisie constructor: (@age, @privilegeConstant) -> worry: -> console.log("My stocks are down 1%!") profit: (hardWork, luck) -> return (@age - 23) * hardWork * (luck + @privilegeConstant) elite = new Bourgeoisie(29, 397) elite.worry() # "My stocks are down 1%!" elite.profit(20, 50) #53640
We declare a class called
Bourgeoisie. Functions on a class are declared as follows:
functionName: (arguments) -> code
The constructor function is named, clearly enough,
constructor. It takes two arguments,
priviligeConstant, and automatically assigns them as instance variables (
@ is the CoffeeScript replacement for
this, and when used in the argument of a constructor automatically assigns the variable to the instance). The constructor is called automatically when you create a new
Bourgeoisie, like at the bottom of the code sample. We also have two other functions. The first,
worry, takes no arguments. The second,
profit, takes two arguments and returns a number.
The Inherited Class
Now we want to have a class that inherits from
Bourgeoisie. We’ll call it
class Senator extends Bourgeoisie worry: -> console.log("The polls are down 1%!") senator = new Senator(45, 992) senator.worry() # "The polls are down 1%!") senator.profit(6, 10) # 132264
This class extends
Bourgeoisie, which means that it has all the characteristics of the parent class. The
profit functions are exactly the same, the only difference is that you make a call to
Senator instead of
Bourgeoisie when constructing an instance.
worry function, on the other hand, is different. The
Senator worries about polls more than stocks, so his
worry overwrites that of the parent class. This overwriting is seen again in a
Student class, shown below.
class Student extends Bourgeoisie worry: -> console.log("Does my privilege inherently make me complicit in the repression of less fortunate classes?") profit: (hardWork, luck, tuition) -> super(hardWork, luck) - tuition student = new Student(21, 89) student.worry() #"Does my privilege inherently make me complicit in the repression of less fortunate classes?" student.profit(10, 10, 10000) #-11980
worry overwrites the parent’s
worry (in an even more dramatic fashion than the Senator’s), and their
profit is also overwritten. However, the overwrite is now dependent on the parent class’s
profit function. It takes that and subtracts the tuition. It’s a bad time to be a student! But what you should really learn from this is the
super keyword, which calls the parent’s version of a function.
But, I Liked Prototypes
Good for you! CoffeeScript gives you convenience, but it still leaves you with power. Let’s use it! Here’s our abbreviated example from last time:
object = (o) -> F = -> F.prototype = o new F() soldier = new Object() soldier.a = jump soldier.r = machineGun sniper = object(soldier) sniper.r = snipe woundedSniper = object(sniper) woundedSniper.a = -> console.log('aaaargh my leg!') woundedSoldier = object(soldier) woundedSoldier.a = woundedSniper.a
This should seem familiar, because 90% of the change was replacing a few
:: instead of
prototype. However, in the Brendan Eich style of prototypes, we only need to use that once, in the
object(o) method. We can also access the
super keywords, but those are used only in constructors – which we have once again hidden away in the
The classical inheritance system in CoffeeScript provides convenience and comfort to the average developer. In addition, the cleaner syntax of CoffeeScript makes implementing a true prototypal system slightly easier. There’s simply no way to lose.