by Dominik Jungowski
22. September 2009
No Comment
After I've already covered normal and static classes, Part 3 is about extending classes. As before, basic knowledge in OOP and JavaScript is needed.
First, let's create a class Human with setters and getters for the age:
function Human()
{
}
Human.prototype._age = 0;
Human.prototype.setAge = function(age)
{
if (typeof age != 'number') {
throw('Invalid Age provided');
}
this._age = age;
};
Human.prototype.getAge = function()
{
return this._age;
};
Since there are no keywords like class, private, public or protected in Javascript it's no surprise there's no keyword extends aswell. In order to extend a class you have to use prototyping:
function Woman(age)
{
this.setAge(age);
}
Woman.prototype = new Human();
Now we've created a new class Woman that inherits all methods and properties from Human by assigning Woman's prototype to new Human(). To show it's easily possible, I've also changed the constructor as it now takes age as parameter. Creating a new object Woman and reading the age looks like this:
var woman = new Woman(22);
alert(woman.getAge());
You can overload methods simply by redifining them. In this case we'll overload the getAge method where we'll add an additional check and then call the parent getAge method. Since you actually don't call the parent method but call the parent method in static way, it is important to add call(this) in order to call the method in the actual context.
Woman.prototype.getAge = function()
{
if (this._age > 100) {
throw('This person is probably already dead!');
}
return Human.prototype.getAge.call(this);
};
Multiple inheritance is possible, but not very easy. For a method using Swiss Inheritance, check this page. Extending static classes might be possible, but I don't know a way. Problem is you need to clone the parent class (which is not that easy in JavaScript), if you write it like this the child becomes the parent and the other way round, meaning if you add a method in the Child it is also available in the parent:
function Cookie()
{
}
Cookie.get = function()
{
return 'something';
};
var CookieChild = Cookie;
alert(CookieChild.get());
Part 4 (probably the last one of the series for now) will cover scoping.
by Dominik Jungowski
15. September 2009
Comments (4)
After I've covered normal classes in Part 1 of the series, the second part will focus on static classes and singletons. As before basic OOP and JavaScript knowledge is needed.
Generally writing and using static classes is monstly the same as normal classes. The difference is that you don't need to instantiate the object with new and you can't use prototyping nor this, since everything is in static context. One useful implementation for static classes is the Registry Design Pattern. First off we create the class with a property to store the registry values in afterwards:
function Registry()
{
}
Registry._data = {};
Right now, I can't really do a lot with this class, that's why I'll create a static method that allows me to set key-value-combinations:
Registry.set = function(key, value) {
Registry._data[key] = value;
}
Now I'm able to register stuff in the registry. Since I don't need an instance of the class I can call my method directly:
Registry.set('userIsAuthorized', false);
I'll leave out the getter you'd still need for a useful registry.
If you want to prevent anyone from writing new Registry() you only have to throw an exception in the constructor:
function Registry()
{
throw('You cannot instantiate Registry');
}
Maybe for some reason you wanna use Registry as a singleton. In that case you have to combine normal class methods and properties with static ones. You write the Registry as a normal class and implement one static property instance and one static method getInstance. The Registry class would then look like this:
function Registry()
{
}
Registry.instance = null;
Registry.getInstance = function() {
if (Registry.instance === null) {
Registry.instance = new Registry();
}
return Registry.instance;
}
Registry.prototype._data = {};
Registry.prototype.set = function(key, value) {
this._data[key] = value;
}
Since JavaScript doesn't have access modifiers like private, public or protected I had to remove the exception from the constructor. You could do it with a randomly generated token passed to the constructor, but this method is not bulletproof like any other I can think of.
In part 3 (that'll come later this week) I will write about extending classes.
by Dominik Jungowski
12. September 2009
Comments (5)
OOP in JavaScript works a bit different than known from other languages. That's why I decided to do a series of "OOP in JavaScript" blogposts, where I want to show how OOP in JavaScript works. The series will discuss topics like creating classes, prototyping, extending classes, static classes, scoping, and so on. To understand these postings a basic knowledge of JavaScript and OOP is needed. This first part is about creating classes/prototyping.
First thing you need to know: There is now keyword class in JavaScript. In order to create a class in JavaScript, all you have to do is to create a function and then create a new class instance by using the known keyword new:
function Product() {}
var product = new Product();
The function we've created is the constructor of our new class. To create methods and properties there are two ways: You can either declare them in the constructor or you can do prototyping.
Declaring it in the constructor:
function Product() {
this.id = 71288;
this.getId = function() {
return this.id;
}
}
Prototyping:
function Product() {}
Product.prototype.id = 71288;
Product.prototype.getId = function() {
return this.id;
}
Personally I prefer prototyping as it is more clear. If you want to call the function getId() it always works the same way with both methods:
var product = new Product();
alert(product.getId());
This class is still quite static, since the id is hardcoded in it. To make it dynamic I just need to modify the constructor to make it accept a config object. Notice that I replaced the id property with a config property that stores the whole config given to the object.
function Product(config) {
this.parseConfig(config);
}
Product.prototype.config = {};
Product.prototype.parseConfig = function(config) {
if (typeof config != 'object') {
throw('Parameter "config" must be of type object');
}
// ID should always be set and a number
if (typeof config.id != 'number') {
throw('Config Parameter config.id must be a number');
}
this.config = config;
}
Product.prototype.getId = function() {
return this.config.id;
}
As you can see I also already implemented checks that the config must always be an object and that an id must always be set and a number. Creating a new instance of the class now looks like this:
var product = new Product({
id: 71288
});
This way we can now dynamically create Product Objects based on Product IDs we read from e.g. a database.
In the second part, that will come within the next few days I will write about static classes.
< August 2009 | Oktober 2009 >