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' );
|
||||
|
||||
|
||||
/**
|
||||
* 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
|
||||
*
|
||||
* @return {Interface} extended interface
|
||||
*/
|
||||
exports.extend = function()
|
||||
module.exports.extend = function()
|
||||
{
|
||||
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': [],
|
||||
} ),
|
||||
|
||||
Interface( {
|
||||
'abstract method': [],
|
||||
} )
|
||||
];
|
||||
|
||||
var BaseType;
|
||||
for ( var i = 0; i < base_types.length; i++ )
|
||||
{
|
||||
'abstract method': [],
|
||||
});
|
||||
BaseType = base_types[ i ];
|
||||
|
||||
assert.ok(
|
||||
( BaseType.prototype.method instanceof Function ),
|
||||
"Interface contains defined abstract methods"
|
||||
);
|
||||
assert.ok(
|
||||
( BaseType.prototype.method instanceof Function ),
|
||||
"Interface contains defined abstract methods"
|
||||
);
|
||||
|
||||
|
||||
var SubType = Interface.extend( BaseType,
|
||||
var SubType = Interface.extend( BaseType,
|
||||
{
|
||||
'abstract second': [],
|
||||
});
|
||||
|
||||
assert.ok(
|
||||
( SubType.prototype instanceof BaseType ),
|
||||
"Generic interface extend method can extend from other interfaces"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
( SubType.prototype.method === BaseType.prototype.method ),
|
||||
"Interface subtypes inherit abstract methods"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
( SubType.prototype.second instanceof Function ),
|
||||
"Interfaces can be extended with additional abstract methods"
|
||||
);
|
||||
|
||||
|
||||
assert.ok(
|
||||
( BaseType.extend instanceof Function ),
|
||||
"Interface contains extend method"
|
||||
);
|
||||
|
||||
|
||||
var SubType2 = BaseType.extend(
|
||||
{
|
||||
'abstract second': [],
|
||||
});
|
||||
|
||||
assert.ok(
|
||||
( SubType2.prototype instanceof BaseType ),
|
||||
"Interface extend method can extend interfaces"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
( SubType2.prototype.second instanceof Function ),
|
||||
"Interfaces can be extended with additional abstract methods using " +
|
||||
"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()
|
||||
{
|
||||
'abstract second': [],
|
||||
});
|
||||
assert.throws( function()
|
||||
{
|
||||
Interface( 'moo' );
|
||||
Interface( 5 );
|
||||
Interface( false );
|
||||
Interface();
|
||||
},
|
||||
TypeError,
|
||||
"Invoking interface module requires object as argument if extending " +
|
||||
"from base interface"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
( SubType.prototype instanceof BaseType ),
|
||||
"Generic interface extend method can extend from other interfaces"
|
||||
);
|
||||
var args = [ {}, 'one', 'two', 'three' ];
|
||||
|
||||
assert.ok(
|
||||
( SubType.prototype.method === BaseType.prototype.method ),
|
||||
"Interface subtypes inherit abstract methods"
|
||||
);
|
||||
// we must only provide one argument if the first argument is an object (the
|
||||
// interface definition)
|
||||
try
|
||||
{
|
||||
Interface.apply( null, args );
|
||||
|
||||
assert.ok(
|
||||
( SubType.prototype.second instanceof Function ),
|
||||
"Interfaces can be extended with additional abstract methods"
|
||||
);
|
||||
|
||||
|
||||
assert.ok(
|
||||
( BaseType.extend instanceof Function ),
|
||||
"Interface contains extend method"
|
||||
);
|
||||
|
||||
|
||||
var SubType2 = BaseType.extend(
|
||||
{
|
||||
'abstract second': [],
|
||||
});
|
||||
|
||||
assert.ok(
|
||||
( SubType2.prototype instanceof BaseType ),
|
||||
"Interface extend method can extend interfaces"
|
||||
);
|
||||
|
||||
assert.ok(
|
||||
( SubType2.prototype.second instanceof Function ),
|
||||
"Interfaces can be extended with additional abstract methods using " +
|
||||
"shorthand extend method"
|
||||
);
|
||||
// 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