This guide explains how to use the single parameter class definition to define or extend a class. It will show you how
it can be used together with @exports
annotation.
#Creating a Class
In a previous guide (Extending a Class) we have seen how to create and extend a class. Now,
we are going to revisit that example but this time we will define the class without having to specify the constructor
outside the cocktail.mix()
method:
Person.js
var cocktail = require('cocktail');
cocktail.mix({
//export the class
'@exports' : module,
//declare the properties
'@properties' : {
greeting : 'Hello'
},
//the constructor is defined inside the mix()
constructor: function(greeting) {
if(greeting) {
this.setGreeting(greeting);
}
}
});
The code above shows how a class is defined. We have specified a greeting
property and a constructor that receives a
parameter for the greeting property. If the property has value then we are going to use the setter to assign the constructor
parameter to the greeting property.
Another annotation is used in this declaration. @exports
allows to define that we are going to export the current mix.
It will take the result of the mix and assign it to the module.exports
variable so we don’t have to create another
variable name for the class and export it or assign the cocktail.mix execution to the module.exports
variable.
#Extending your Class
The Single Parameter Class Definition can be applied when you pass the subject as a Object literal with a constructor
definition as we saw before. @extends
annotation has the same effect. If you want to extend from a class Person
you can use the single parameter class definition and use the @exports
annotation as follows:
Pirate.js
var cocktail = require('cocktail'),
Person = require('./Person');
cocktail.mix({
'@exports' : module,
'@extends' : Person,
greeting: 'Ahoy'
});
#Traits and Talents
We have said that Traits & Talents are just a special type of class where you only define behavior. It is very common
that a Trait will require a method to be defined in order to work with your class.
We are going to define the Greetable trait using the Single Parameter Class Definition and then apply it to our Person
class.
Greetable.js
var cocktail = require('cocktail');
cocktail.mix({
'@exports' : module,
'@requires' : ['getGreeting'],
sayHi: function(){
var greeting = this.getGreeting();
console.log(greeting + "!");
}
});
And now we can refactor our previous Person
class:
Person.js
var cocktail = require('cocktail'),
Greetable = require('./Greetable.js');
cocktail.mix({
'@exports' : module,
'@traits' : [Greetable],
'@properties' : {
greeting : 'Hello'
},
constructor: function(greeting) {
if(greeting) {
this.setGreeting(greeting);
}
}
});
Notice that our Greetable trait declares a getGreeting
as a required method. We are applying the trait to our
Person
class. We didn’t define the getter for greeting
property but it is created when we declare @properties
annotation.
Now let’s use our classes in a simple example. We can create a couple Pirates and Persons and make them sayHi
index.js
var Person = require('./Person'),
Pirate = require('./Pirate'),
people = [],
i;
people.push(new Pirate());
people.push(new Person());
for (i = 0; i < people.length; i++) {
people[i].sayHi();
}
Runing index.js
$ node index.js
Ahoy!
Hello!
That’s it, as you can see we use cocktail to help with classes definitions but it is not required to use the classes.