Merge branch 'master' into doc/master
commit
03f53a8924
|
@ -314,27 +314,52 @@ function overrideMethod( super_method, new_method, instCallback )
|
||||||
// __super property
|
// __super property
|
||||||
var override = null;
|
var override = null;
|
||||||
|
|
||||||
|
// are we overriding?
|
||||||
if ( new_method )
|
if ( new_method )
|
||||||
{
|
{
|
||||||
override = function()
|
override = function()
|
||||||
{
|
{
|
||||||
|
var context = instCallback( this ) || this,
|
||||||
|
retval = undefined
|
||||||
|
;
|
||||||
|
|
||||||
// the _super property will contain the parent method
|
// the _super property will contain the parent method
|
||||||
this.__super = super_method;
|
this.__super = super_method;
|
||||||
|
|
||||||
var retval = new_method.apply(
|
retval = new_method.apply( context, arguments );
|
||||||
( instCallback( this ) || this ), arguments
|
|
||||||
);
|
// if the value returned from the method was the context that we
|
||||||
|
// passed in, return the actual instance (to ensure we do not break
|
||||||
|
// encapsulation)
|
||||||
|
if ( retval === context )
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
return retval;
|
return retval;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
|
// we are defining a new method
|
||||||
override = function()
|
override = function()
|
||||||
{
|
{
|
||||||
return super_method.apply(
|
var context = instCallback( this ) || this,
|
||||||
( instCallback( this ) || this ), arguments
|
retval = undefined
|
||||||
);
|
;
|
||||||
|
|
||||||
|
// invoke the method
|
||||||
|
retval = super_method.apply( context, arguments );
|
||||||
|
|
||||||
|
// if the value returned from the method was the context that we
|
||||||
|
// passed in, return the actual instance (to ensure we do not break
|
||||||
|
// encapsulation)
|
||||||
|
if ( retval === context )
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
}
|
||||||
|
|
||||||
|
return retval;
|
||||||
};
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,6 +45,7 @@ var common = require( './common' ),
|
||||||
'protected protf': protf,
|
'protected protf': protf,
|
||||||
'private privf': privf,
|
'private privf': privf,
|
||||||
|
|
||||||
|
|
||||||
'public getProp': function( name )
|
'public getProp': function( name )
|
||||||
{
|
{
|
||||||
// return property, allowing us to break encapsulation for
|
// return property, allowing us to break encapsulation for
|
||||||
|
@ -60,13 +61,31 @@ var common = require( './common' ),
|
||||||
{
|
{
|
||||||
this[ name ] = value;
|
this[ name ] = value;
|
||||||
},
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'public getSelf': function()
|
||||||
|
{
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
|
||||||
|
|
||||||
|
'public getSelfOverride': function()
|
||||||
|
{
|
||||||
|
// override me
|
||||||
|
},
|
||||||
}),
|
}),
|
||||||
|
|
||||||
// instance of Foo
|
// instance of Foo
|
||||||
foo = Foo(),
|
foo = Foo(),
|
||||||
|
|
||||||
// subtype
|
// subtype
|
||||||
SubFoo = Foo.extend( {} ),
|
SubFoo = Foo.extend({
|
||||||
|
'public getSelfOverride': function()
|
||||||
|
{
|
||||||
|
// return this from overridden method
|
||||||
|
return this;
|
||||||
|
},
|
||||||
|
}),
|
||||||
sub_foo = SubFoo()
|
sub_foo = SubFoo()
|
||||||
;
|
;
|
||||||
|
|
||||||
|
@ -308,3 +327,38 @@ var common = require( './common' ),
|
||||||
);
|
);
|
||||||
} )();
|
} )();
|
||||||
|
|
||||||
|
|
||||||
|
/**
|
||||||
|
* When a method is called, 'this' is bound to the property object containing
|
||||||
|
* private and protected members. Returning 'this' would therefore be a very bad
|
||||||
|
* thing. Not only would it break encapsulation, but it would likely have other
|
||||||
|
* problems down the road.
|
||||||
|
*
|
||||||
|
* Therefore, we have to check the return value of the method. If the return
|
||||||
|
* value is the property object that it was bound to, we need to replace the
|
||||||
|
* return value with the actual class instance. This allows us to transparently
|
||||||
|
* enforce encapsulation. How sweet is that?
|
||||||
|
*/
|
||||||
|
( function testReturningSelfFromMethodShouldReturnInstanceNotPropObj()
|
||||||
|
{
|
||||||
|
assert.deepEqual(
|
||||||
|
foo.getSelf(),
|
||||||
|
foo,
|
||||||
|
"Returning 'this' from a method should return instance of self"
|
||||||
|
);
|
||||||
|
|
||||||
|
// what happens in the case of inheritance?
|
||||||
|
assert.deepEqual(
|
||||||
|
sub_foo.getSelf(),
|
||||||
|
sub_foo,
|
||||||
|
"Returning 'this' from a super method should return the subtype"
|
||||||
|
);
|
||||||
|
|
||||||
|
// finally, overridden methods should still return the instance
|
||||||
|
assert.deepEqual(
|
||||||
|
sub_foo.getSelfOverride(),
|
||||||
|
sub_foo,
|
||||||
|
"Returning 'this' from a overridden method should return the subtype"
|
||||||
|
);
|
||||||
|
} )();
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue