`override' implies `virtual'
This behavior is consistent with other OO languages like C++ and C# that do not have virtual methods by default. This solution isn't ideal, but I don't have time for a larger refactoring right now. I sat on this change for a good few weeks before committing it unchanged. * lib/MemberBuilderValidator.js (validateMethod): Allow override of supertype overrides. * test/*: Stripped `virtual' keyword where appropriate. * doc/classes.texi (Inheritance): Update to state that `override' implies `virtual'.master
parent
311118de81
commit
90fd1a8d08
|
@ -749,12 +749,10 @@ One of the following conditions must always be true:
|
|||
@var{dfn\_n\^C} is declared with the @ref{Member Keywords,,@code{virtual}}
|
||||
keyword and @var{dfn\_n\^C'} is declared with the
|
||||
@ref{Member Keywords,,@code{override}} keyword.
|
||||
@itemize
|
||||
@item
|
||||
Note that @var{dfn\_n\^C'} will not become @ref{Member Keywords,,@code{virtual}}
|
||||
by default (unlike languages such as C++); they must be explicitly
|
||||
declared as such.
|
||||
@end itemize
|
||||
@item
|
||||
@var{dfn\_n\^C} is declared with the @ref{Member Keywords,,@code{override}}
|
||||
keyword and @var{dfn\_n\^C'} is also declared with the
|
||||
@ref{Member Keywords,,@code{override}} keyword.
|
||||
@item
|
||||
@var{dfn\_n\^C} is declared with the @ref{Member Keywords,,@code{abstract}}
|
||||
keyword and @var{dfn\_n\^C'} omits the @ref{Member Keywords,,@code{override}}
|
||||
|
@ -860,10 +858,24 @@ classes using ease.js?
|
|||
console.log( 'Walking the dog on two feet' );
|
||||
}
|
||||
} );
|
||||
|
||||
// supertype override is implicitly virtual
|
||||
var ReallyLazyDog = LazyDog.extend(
|
||||
{
|
||||
'override public walk': function()
|
||||
{
|
||||
// ...
|
||||
}
|
||||
} );
|
||||
@end verbatim
|
||||
@caption{Inheritance in ease.js}
|
||||
@end float
|
||||
|
||||
(The above inheritance tree is a bad idea and is for illustration
|
||||
purposes only:
|
||||
if you want to layer attributes,
|
||||
use Traits or a composition-based pattern like Decorators.)
|
||||
|
||||
You should already understand how to define a class (@pxref{Defining
|
||||
Classes}). The above example introduced two means of @dfn{extending}
|
||||
classes -- defining a new class that inherits from a parent:
|
||||
|
|
|
@ -211,7 +211,8 @@ exports.prototype.validateMethod = function(
|
|||
}
|
||||
|
||||
// disallow overriding non-virtual methods
|
||||
if ( keywords[ 'override' ] && !( prev_keywords[ 'virtual' ] ) )
|
||||
if ( keywords[ 'override' ]
|
||||
&& !( prev_keywords[ 'virtual' ] || prev_keywords[ 'override' ] ) )
|
||||
{
|
||||
if ( !( keywords[ 'abstract' ] ) )
|
||||
{
|
||||
|
|
|
@ -192,9 +192,18 @@ require( 'common' ).testCase(
|
|||
|
||||
|
||||
/**
|
||||
* Overriding a method in ease.js does not immediately make it virtual.
|
||||
* Rather, the virtual keyword must be explicitly specified. Let's ensure
|
||||
* that it is permitted.
|
||||
* An override is implicitly virtual. This was not always the case:
|
||||
* prior to v0.2.9, an override did not imply virtual.
|
||||
*/
|
||||
'Can override overridden method with concrete method': function()
|
||||
{
|
||||
this.quickKeywordMethodTest( [ 'override' ], null, [ 'override' ] );
|
||||
},
|
||||
|
||||
|
||||
/**
|
||||
* For legacy reasons; see above test. In the future, this might
|
||||
* trigger a notice, since it's redundant. No harm in being explicit!
|
||||
*/
|
||||
'Can declare override as virtual': function()
|
||||
{
|
||||
|
|
|
@ -485,7 +485,7 @@ require( 'common' ).testCase(
|
|||
|
||||
var T1 = this.Sut.extend( C,
|
||||
{
|
||||
'virtual abstract override foo': function()
|
||||
'abstract override foo': function()
|
||||
{
|
||||
return 3 + this.__super();
|
||||
},
|
||||
|
@ -493,7 +493,7 @@ require( 'common' ).testCase(
|
|||
|
||||
var T2 = this.Sut.extend( C,
|
||||
{
|
||||
'virtual abstract override foo': function()
|
||||
'abstract override foo': function()
|
||||
{
|
||||
return 13 + this.__super();
|
||||
},
|
||||
|
@ -533,7 +533,7 @@ require( 'common' ).testCase(
|
|||
|
||||
var T1 = this.Sut.extend( C,
|
||||
{
|
||||
'virtual override foo': function()
|
||||
'override foo': function()
|
||||
{
|
||||
return 3 + this.__super();
|
||||
},
|
||||
|
@ -541,7 +541,7 @@ require( 'common' ).testCase(
|
|||
|
||||
var T2 = this.Sut.extend( C,
|
||||
{
|
||||
'virtual override foo': function()
|
||||
'override foo': function()
|
||||
{
|
||||
return 13 + this.__super();
|
||||
},
|
||||
|
@ -603,7 +603,7 @@ require( 'common' ).testCase(
|
|||
var T2 = this.Sut.extend( C,
|
||||
{
|
||||
// T1 provides a concrete method that we can override
|
||||
'virtual abstract override concrete': function()
|
||||
'abstract override concrete': function()
|
||||
{
|
||||
return 5 + this.__super();
|
||||
},
|
||||
|
|
|
@ -137,7 +137,7 @@ require( 'common' ).testCase(
|
|||
|
||||
var Ta = this.Sut.implement( I ).extend(
|
||||
{
|
||||
'virtual abstract override foo': function()
|
||||
'abstract override foo': function()
|
||||
{
|
||||
called.a = true;
|
||||
this.__super();
|
||||
|
@ -182,7 +182,7 @@ require( 'common' ).testCase(
|
|||
|
||||
var T = this.Sut.implement( I ).extend(
|
||||
{
|
||||
'virtual abstract override foo': function()
|
||||
'abstract override foo': function()
|
||||
{
|
||||
called++;
|
||||
this.__super();
|
||||
|
|
|
@ -340,7 +340,7 @@ require( 'common' ).testCase(
|
|||
this.assertStrictEqual( expected,
|
||||
this.Class.use( T ).extend(
|
||||
{
|
||||
'override virtual foo': function()
|
||||
'override foo': function()
|
||||
{
|
||||
return this.__super();
|
||||
},
|
||||
|
|
|
@ -55,9 +55,9 @@ var Cv = Class.implement( I ).extend(
|
|||
|
||||
var To = Trait.implement( I ).extend(
|
||||
{
|
||||
'virtual abstract override a': function() {},
|
||||
'virtual abstract override b': function() {},
|
||||
'virtual abstract override c': function() {},
|
||||
'abstract override a': function() {},
|
||||
'abstract override b': function() {},
|
||||
'abstract override c': function() {},
|
||||
} );
|
||||
|
||||
|
||||
|
|
Loading…
Reference in New Issue