In practice, we can define the interface in comments and implement it in actual code
For example:
/*
interface Composite {
function add(child);
function remove(child);
function getChild(index);
}
interface FormItem {
function save();
}
*/
var CompositeForm = function(id, method, action) { // implements Composite, FormItem
...
};
// Implement the Composite interface.
CompositeForm.prototype.add = function(child) {
...
};
CompositeForm.prototype.remove = function( child) {
...
};
CompositeForm.prototype.getChild = function(index) {
...
};
// Implement the FormItem interface.
CompositeForm.prototype.save = function() {
...
};
Have the programmers who implemented the interface implemented all these interfaces? We can't guarantee it! Because there is no way to check whether the interface is implemented
We need a mechanism to check whether the interface is implemented, which can be like this:
/*
interface Composite {
function add(child);
function remove(child);
function getChild(index);
}
interface FormItem {
function save();
}
*/
var CompositeForm = function(id, method, action) {
this.implementsInterfaces = ['Composite ', 'FormItem'];
...
};
...
function addForm(formInstance) {
if(!implements(formInstance, 'Composite', 'FormItem' )) {
throw new Error("Object does not implement a required interface.");
}
...
}
// The implements function, which checks to see if an object declares that it
// implements the required interfaces.
function implements(object) {
for(var i = 1; i < arguments.length; i ) { // Looping through all arguments
// after the first one.
var interfaceName = arguments[i];
var interfaceFound = false;
for(var j = 0; j < object.implementsInterfaces.length; j ) {
if(object.implementsInterfaces[j] == interfaceName) {
interfaceFound = true;
break;
}
}
if(!interfaceFound) {
return false; // An interface was not found.
}
}
return true; // All interfaces were found.
}
This method allows programmers to When writing, indicate which interfaces are implemented: this.implementsInterfaces = ['Composite', 'FormItem']; When calling, use the implements method to determine whether it is implemented. It is theoretically feasible and it is very likely that the implementation has been written. 'Composite' interface, but there is no add method in the code! Therefore, we need to check whether the class that implements the interface contains the methods in the interface! Therefore, the interface must be freed from comments:
// Interfaces.
var Composite = new Interface('Composite', ['add', 'remove', 'getChild']);
var FormItem = new Interface('FormItem', ['save']);
// CompositeForm class
var CompositeForm = function(id, method, action) { // implements Composite, FormItem
...
};
...
function addForm(formInstance) {
Interface.ensureImplements(formInstance, Composite, FormItem);
// This function will throw an error if a required method is not implemented,
// halting execution of the function.
// All code beneath this line will be executed only if the checks pass.
...
}
defines the interfaces Composite, FormItem, and CompositeForm implements these two interfaces. When using, use Interface.ensureImplements to check whether formInstance implements all methods in these two interfaces.
Let’s take a look at the definition of Interface: two parameters, the first parameter is the interface name, and the second parameter is the method array contained in the interface
// Constructor.
var Interface = function(name, methods) {
if(arguments.length != 2) {
throw new Error("Interface constructor called with " arguments.length
"arguments, but expected exactly 2.");
}
this.name = name;
this.methods = [];
for(var i = 0, len = methods.length; i < len; i ) {
if(typeof methods[i] !== 'string') {
throw new Error(" Interface constructor expects method names to be "
"passed in as a string.");
}
this.methods.push(methods[i]);
}
};
为Interface 添加建议接口是否实现的静态方法
// Constructor.
Interface.ensureImplements = function(object) {
if(arguments.length < 2) {
throw new Error("Function Interface.ensureImplements called with "
arguments.length "arguments, but expected at least 2.");
}
for(var i = 1, len = arguments.length; i < len; i ) {
var interface = arguments[i];
if(interface.constructor !== Interface) {
throw new Error("Function Interface.ensureImplements expects arguments"
"two and above to be instances of Interface.");
}
for(var j = 0, methodsLen = interface.methods.length; j < methodsLen; j ) {
var method = interface.methods[j];
if(!object[method] || typeof object[method] !== 'function') {
throw new Error("Function Interface.ensureImplements: object "
"does not implement the " interface.name
" interface. Method " method " was not found.");
}
}
}
};