The interface module may now be invoked, providing a more natural looking means of declaring interfaces
parent
4987856a46
commit
3f915d3644
|
@ -27,12 +27,49 @@ var util = require( './util' ),
|
||||||
Class = require( './class' );
|
Class = require( './class' );
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* This module may be invoked in order to provide a more natural looking
|
||||||
|
* interface definition
|
||||||
|
*
|
||||||
|
* Only new interfaces may be created using this method. They cannot be
|
||||||
|
* extended. To extend an existing interface, call its extend() method, or use
|
||||||
|
* the extend() method of this module.
|
||||||
|
*
|
||||||
|
* @param {Object} def interface definition
|
||||||
|
*
|
||||||
|
* @return {Interface} new interface
|
||||||
|
*/
|
||||||
|
module.exports = function( def )
|
||||||
|
{
|
||||||
|
// if the first argument is an object, then we are declaring an interface
|
||||||
|
if ( typeof def !== 'object' )
|
||||||
|
{
|
||||||
|
throw TypeError(
|
||||||
|
"Must provide interface definition when declaring interface"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
// ensure we have the proper number of arguments (if they passed in too
|
||||||
|
// many, it may signify that they don't know what they're doing, and likely
|
||||||
|
// they're not getting the result they're looking for)
|
||||||
|
if ( arguments.length > 1 )
|
||||||
|
{
|
||||||
|
throw Error(
|
||||||
|
"Expecting one argument for Interface definition; " +
|
||||||
|
arguments.length + " given."
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
return extend( def );
|
||||||
|
};
|
||||||
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Creates an interface
|
* Creates an interface
|
||||||
*
|
*
|
||||||
* @return {Interface} extended interface
|
* @return {Interface} extended interface
|
||||||
*/
|
*/
|
||||||
exports.extend = function()
|
module.exports.extend = function()
|
||||||
{
|
{
|
||||||
return extend.apply( this, arguments );
|
return extend.apply( this, arguments );
|
||||||
};
|
};
|
||||||
|
|
|
@ -83,57 +83,113 @@ assert.doesNotThrow(
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
var BaseType = Interface.extend(
|
// There's a couple ways to create interfaces. Test 'em both.
|
||||||
{
|
var base_types = [
|
||||||
|
Interface.extend(
|
||||||
|
{
|
||||||
'abstract method': [],
|
'abstract method': [],
|
||||||
});
|
} ),
|
||||||
|
|
||||||
assert.ok(
|
Interface( {
|
||||||
|
'abstract method': [],
|
||||||
|
} )
|
||||||
|
];
|
||||||
|
|
||||||
|
var BaseType;
|
||||||
|
for ( var i = 0; i < base_types.length; i++ )
|
||||||
|
{
|
||||||
|
BaseType = base_types[ i ];
|
||||||
|
|
||||||
|
assert.ok(
|
||||||
( BaseType.prototype.method instanceof Function ),
|
( BaseType.prototype.method instanceof Function ),
|
||||||
"Interface contains defined abstract methods"
|
"Interface contains defined abstract methods"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
var SubType = Interface.extend( BaseType,
|
var SubType = Interface.extend( BaseType,
|
||||||
{
|
{
|
||||||
'abstract second': [],
|
'abstract second': [],
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
( SubType.prototype instanceof BaseType ),
|
( SubType.prototype instanceof BaseType ),
|
||||||
"Generic interface extend method can extend from other interfaces"
|
"Generic interface extend method can extend from other interfaces"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
( SubType.prototype.method === BaseType.prototype.method ),
|
( SubType.prototype.method === BaseType.prototype.method ),
|
||||||
"Interface subtypes inherit abstract methods"
|
"Interface subtypes inherit abstract methods"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
( SubType.prototype.second instanceof Function ),
|
( SubType.prototype.second instanceof Function ),
|
||||||
"Interfaces can be extended with additional abstract methods"
|
"Interfaces can be extended with additional abstract methods"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
( BaseType.extend instanceof Function ),
|
( BaseType.extend instanceof Function ),
|
||||||
"Interface contains extend method"
|
"Interface contains extend method"
|
||||||
);
|
);
|
||||||
|
|
||||||
|
|
||||||
var SubType2 = BaseType.extend(
|
var SubType2 = BaseType.extend(
|
||||||
{
|
{
|
||||||
'abstract second': [],
|
'abstract second': [],
|
||||||
});
|
});
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
( SubType2.prototype instanceof BaseType ),
|
( SubType2.prototype instanceof BaseType ),
|
||||||
"Interface extend method can extend interfaces"
|
"Interface extend method can extend interfaces"
|
||||||
);
|
);
|
||||||
|
|
||||||
assert.ok(
|
assert.ok(
|
||||||
( SubType2.prototype.second instanceof Function ),
|
( SubType2.prototype.second instanceof Function ),
|
||||||
"Interfaces can be extended with additional abstract methods using " +
|
"Interfaces can be extended with additional abstract methods using " +
|
||||||
"shorthand extend method"
|
"shorthand extend method"
|
||||||
);
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* The interface invocation action depends on what arguments are passed in. One
|
||||||
|
* use is to pass in an object as the first and only argument, creating a new
|
||||||
|
* interface with no supertype.
|
||||||
|
*/
|
||||||
|
( function testInvokingInterfaceModuleRequiresObjectAsArgumentIfExtending()
|
||||||
|
{
|
||||||
|
assert.throws( function()
|
||||||
|
{
|
||||||
|
Interface( 'moo' );
|
||||||
|
Interface( 5 );
|
||||||
|
Interface( false );
|
||||||
|
Interface();
|
||||||
|
},
|
||||||
|
TypeError,
|
||||||
|
"Invoking interface module requires object as argument if extending " +
|
||||||
|
"from base interface"
|
||||||
|
);
|
||||||
|
|
||||||
|
var args = [ {}, 'one', 'two', 'three' ];
|
||||||
|
|
||||||
|
// we must only provide one argument if the first argument is an object (the
|
||||||
|
// interface definition)
|
||||||
|
try
|
||||||
|
{
|
||||||
|
Interface.apply( null, args );
|
||||||
|
|
||||||
|
// if all goes well, we don't get to this line
|
||||||
|
assert.fail(
|
||||||
|
"Only one argument for interface definitions is permitted"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
catch ( e )
|
||||||
|
{
|
||||||
|
assert.notEqual(
|
||||||
|
e.toString().match( args.length + ' given' ),
|
||||||
|
null,
|
||||||
|
"Interface invocation should give argument count on error"
|
||||||
|
);
|
||||||
|
}
|
||||||
|
} )();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue