Writing better OO with ATLAS – part III
In the previous posts, I’ve spoken about classes and namespaces. Today I’m writing about interfaces. Interfaces are contracts which define one or more abstract members. It’s important to note that interface usage is slightly different from what we’re used to in classical OO languages (which is something we expected due to the way Javascript works). For instance, you won’t be able to perform casts from a class to an interface, but you can still see if an object implements an interface. Let’s see how we can define an interface:
LA.IStudent = function(){ this.printInfo = Function.abstractMethod;}LA.IStudent.registerInterface( "LA.IStudent" );
abstractMethod is introduced by ATLAS and it throws an exception. This ensures that we must “override” the method on a class that implements the interface. Btw, let’s change the Student class so that it implements the previous interface:
LA.Student = function( age, name ){
LA.Student.initializeBase( this );
var _name = name;
var _age = age;
this.get_name = function(){ return _name; }
this.set_name = function( value ){ _name = value; }
this.get_age = function(){ return _age; }
this.set_age = function( value ){ _age = value; }
}
LA.Student.registerClass( "LA.Student", null, LA.IStudent );
The only thing new here is the last parameter passed to the registerClass method. In the previous example, the class implements the interface but didn’t “override” the printInfo method. If we instantiate the class and call the method, we’ll have an exception. To avoid that, we must override the printInfo method by adding a new definition in our class:
this.printInfo = function(){ return _name + “ “ + _age;}
Now, we can have similar code to this one:
var std = new LA.Student( 30, "Luis" );alert( std.printInfo() );
As I’ve said, when we build an interface, we’re introducing a contract. Most of the times, it’s normal to use an interface to see if an object has adhered to that contract: if it does, then we know that it has some known members which we can use. We have two options: we can check if an object implements an interface or we can also check if a type implements an interface.
Let’s start by seeing if an object implements a specific interface. To do that, we’re changing the previous example so that the printInfo method call is made only if the object implements the interface:
var std = new LA.Student( 30, "Luis" );
if( LA.IStudent.isimplementedBy( std ) ){
alert( std.printInfo() );
}
On the other hand, we could also use the object that represents the class definition:
var std = new LA.Student( 30, "Luis" );
if( LA.Student.implementsInterface( "LA.IStudent" ) ){
alert( std.printInfo() );
}
Btw, you should also note that interfaces are kept in an internal list (maintained by the object that represents the class) and it goes through an initialization process which is responsible for adding the interface members defined by the interface to the class.
I guess this is all you need to know about interfaces.