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}} @var{dfn\_n\^C} is declared with the @ref{Member Keywords,,@code{virtual}}
keyword and @var{dfn\_n\^C'} is declared with the keyword and @var{dfn\_n\^C'} is declared with the
@ref{Member Keywords,,@code{override}} keyword. @ref{Member Keywords,,@code{override}} keyword.
@itemize
@item @item
Note that @var{dfn\_n\^C'} will not become @ref{Member Keywords,,@code{virtual}} @var{dfn\_n\^C} is declared with the @ref{Member Keywords,,@code{override}}
by default (unlike languages such as C++); they must be explicitly keyword and @var{dfn\_n\^C'} is also declared with the
declared as such. @ref{Member Keywords,,@code{override}} keyword.
@end itemize
@item @item
@var{dfn\_n\^C} is declared with the @ref{Member Keywords,,@code{abstract}} @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}} 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' ); console.log( 'Walking the dog on two feet' );
} }
} ); } );
// supertype override is implicitly virtual
var ReallyLazyDog = LazyDog.extend(
{
'override public walk': function()
{
// ...
}
} );
@end verbatim @end verbatim
@caption{Inheritance in ease.js} @caption{Inheritance in ease.js}
@end float @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 You should already understand how to define a class (@pxref{Defining
Classes}). The above example introduced two means of @dfn{extending} Classes}). The above example introduced two means of @dfn{extending}
classes -- defining a new class that inherits from a parent: 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 // disallow overriding non-virtual methods
if ( keywords[ 'override' ] && !( prev_keywords[ 'virtual' ] ) ) if ( keywords[ 'override' ]
&& !( prev_keywords[ 'virtual' ] || prev_keywords[ 'override' ] ) )
{ {
if ( !( keywords[ 'abstract' ] ) ) if ( !( keywords[ 'abstract' ] ) )
{ {

View File

@ -192,9 +192,18 @@ require( 'common' ).testCase(
/** /**
* Overriding a method in ease.js does not immediately make it virtual. * An override is implicitly virtual. This was not always the case:
* Rather, the virtual keyword must be explicitly specified. Let's ensure * prior to v0.2.9, an override did not imply virtual.
* that it is permitted. */
'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() 'Can declare override as virtual': function()
{ {

View File

@ -485,7 +485,7 @@ require( 'common' ).testCase(
var T1 = this.Sut.extend( C, var T1 = this.Sut.extend( C,
{ {
'virtual abstract override foo': function() 'abstract override foo': function()
{ {
return 3 + this.__super(); return 3 + this.__super();
}, },
@ -493,7 +493,7 @@ require( 'common' ).testCase(
var T2 = this.Sut.extend( C, var T2 = this.Sut.extend( C,
{ {
'virtual abstract override foo': function() 'abstract override foo': function()
{ {
return 13 + this.__super(); return 13 + this.__super();
}, },
@ -533,7 +533,7 @@ require( 'common' ).testCase(
var T1 = this.Sut.extend( C, var T1 = this.Sut.extend( C,
{ {
'virtual override foo': function() 'override foo': function()
{ {
return 3 + this.__super(); return 3 + this.__super();
}, },
@ -541,7 +541,7 @@ require( 'common' ).testCase(
var T2 = this.Sut.extend( C, var T2 = this.Sut.extend( C,
{ {
'virtual override foo': function() 'override foo': function()
{ {
return 13 + this.__super(); return 13 + this.__super();
}, },
@ -603,7 +603,7 @@ require( 'common' ).testCase(
var T2 = this.Sut.extend( C, var T2 = this.Sut.extend( C,
{ {
// T1 provides a concrete method that we can override // T1 provides a concrete method that we can override
'virtual abstract override concrete': function() 'abstract override concrete': function()
{ {
return 5 + this.__super(); return 5 + this.__super();
}, },

View File

@ -137,7 +137,7 @@ require( 'common' ).testCase(
var Ta = this.Sut.implement( I ).extend( var Ta = this.Sut.implement( I ).extend(
{ {
'virtual abstract override foo': function() 'abstract override foo': function()
{ {
called.a = true; called.a = true;
this.__super(); this.__super();
@ -182,7 +182,7 @@ require( 'common' ).testCase(
var T = this.Sut.implement( I ).extend( var T = this.Sut.implement( I ).extend(
{ {
'virtual abstract override foo': function() 'abstract override foo': function()
{ {
called++; called++;
this.__super(); this.__super();

View File

@ -340,7 +340,7 @@ require( 'common' ).testCase(
this.assertStrictEqual( expected, this.assertStrictEqual( expected,
this.Class.use( T ).extend( this.Class.use( T ).extend(
{ {
'override virtual foo': function() 'override foo': function()
{ {
return this.__super(); return this.__super();
}, },

View File

@ -55,9 +55,9 @@ var Cv = Class.implement( I ).extend(
var To = Trait.implement( I ).extend( var To = Trait.implement( I ).extend(
{ {
'virtual abstract override a': function() {}, 'abstract override a': function() {},
'virtual abstract override b': function() {}, 'abstract override b': function() {},
'virtual abstract override c': function() {}, 'abstract override c': function() {},
} ); } );