Now that we have a way to declare and model interfaces, we need to augment the class declaration mechanism to support interfaces. First, we will change the class declaration syntax to allow zero or more interfaces to be specified along with a superclass. If the second parameter to the declare method is a constructor, it is the superclass. If the second parameter is an array, the first element must be the superclass constructor and any additional elements are interfaces. Here is an example of the new syntax.
xclass.declare("animal.mammal.Human",
[ animal.Biped, animal.Reader, animal.Singer, animal.Swimmer ], {
Here are the modifications to XClass.declare to process the new argument list.
var classList = [];
if ( superclass instanceof Array ) {
classList = superclass;
superclass = classList.shift();
}
The following code is added to process the remaining class list after the superclass is extracted. Each remaining element must be an interface.
var interfaces = cproto.interfaces = [ ];
for ( var i = 0; i < classList.length; ++i ) {
var cl = classList[i];
var position = i + 2;
if ( !cl ) {
throw(this.messages[3].format(position));
}
else if ( cl instanceof XInterface ) {
interfaces.push(cl);
}
else {
throw(this.messages[4].format(position));
}
}
Once the prototype for the new class is complete, the following code will iterate over the interfaces and verify that each method is implemented. A warning is output to the JavaScript console if a method is not implemented.
for ( var i = 0; i < interfaces.length; ++i ) {
var xi = interfaces[i];
var methods = xi.methods;
console.log(this.messages[5].format(xi.className, methods));
for ( var j = 0; j < methods.length; ++j ) {
var methodName = xi.methods[j];
var f = cproto[methodName];
if ( !(f && f instanceof Function) ) {
var s = xi.namespace.fullName() + "." + methodName;
throw(this.messages[6].format(s));
}
}
}
The XObject.implements
method will test for
for implementation of an interface at runtime. It returns true
if this object implements the specified interface.
implements: function(xinterface) {
return this.constructor.prototype.interfaces.contains(xinterface);
}
Next we will demonstrate the use of interfaces.