1
0
Fork 0

`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
Mike Gerwitz 2017-02-01 00:09:59 -05:00
parent 311118de81
commit 90fd1a8d08
Signed by: mikegerwitz
GPG Key ID: 8C917B7F5DC51BA2
7 changed files with 43 additions and 21 deletions

View File

@ -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:

View File

@ -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' ] ) )
{

View File

@ -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()
{

View File

@ -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();
},

View File

@ -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();

View File

@ -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();
},

View File

@ -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() {},
} );