1
0
Fork 0

Constructor virtual by default

* lib/ClassBuilder.js (_keywordParser): Make __construct virtual.
* test/Class/ConstructorTest.js: Add test.

* doc/classes.texi (Constructors): Update documentation.
master
Mike Gerwitz 2017-01-02 23:28:28 -05:00
parent e39ff83b40
commit 92c57c8ffe
Signed by: mikegerwitz
GPG Key ID: 8C917B7F5DC51BA2
3 changed files with 62 additions and 4 deletions

View File

@ -568,6 +568,25 @@ Constructors are always public;
It is not permitted to make a constructor protected or private
(@pxref{Access Modifiers}).
Unlike all other methods,
constructors are @ref{Member Keywords,,@code{virtual}} by default.
Many other languages (C++, Java, C#, and others) do not inherit
class constructors from their supertypes.
ease.js classes are prototypes,
and uninstantiated prototypes are functions (constructors),
so classes are effectively first-class objects in JavaScript.
Consequently,
they can be passed around and invoked like any other function,
which can be a convenient alternative to factories
(and a transparent alternative to functions that create objects).
It is therefore useful to have the constructor as part of the class's
public API.
However,
it is also important that subtypes always be able to override the
constructor (@pxref{Overriding Methods});
otherwise subtypes may not be able to initialize properly,
making for a very clumsy implementation.
Constructors are optional,
and no constructor is defined by default.@footnote{
That is, no user-facing constructor is defined by default;

View File

@ -1,7 +1,8 @@
/**
* Handles building of classes
*
* Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016 Free Software Foundation, Inc.
* Copyright (C) 2011, 2012, 2013, 2014, 2015, 2016, 2017
* Free Software Foundation, Inc.
*
* This file is part of GNU ease.js.
*
@ -687,9 +688,8 @@ exports.prototype.buildMembers = function buildMembers(
/**
* Member keyword parser
*
* In reality, this parser is simply intended to override names where there
* are applicable aliases; all keyword parsing is kept to the original
* implementation.
* This parser handles aliases and constructor virtualization; all keyword
* parsing is kept to the original implementation.
*
* @param {string} prop property to parse
*
@ -705,6 +705,12 @@ function _keywordParser( prop )
result.name = alias;
}
// constructors are always virtual by default (exception to the rule)
if ( result.name === '__construct' )
{
result.keywords[ 'virtual' ] = true;
}
return result;
}

View File

@ -218,6 +218,39 @@ require( 'common' ).testCase(
},
/**
* This one is a bit of an interesting case. Information can be found
* in the manual, but for the sake of this test, all we need to know is
* that we should be able to override `__construct' without having
* provided the `virtual' keyword on the supertype. This differs from
* all other methods which are non-virtual by default.
*/
'@each(ctors) Constructor is virtual by default': function( name )
{
var _self = this;
this.assertDoesNotThrow( function()
{
var sub_called = false;
// not explicitly virtual
var base_dfn = {};
base_dfn[ name ] = function() {};
var sub_dfn = {};
sub_dfn[ 'override ' + name ] = function()
{
sub_called = true;
};
_self.Sut.extend( _self.Sut( base_dfn ), sub_dfn )();
// sanity check
_self.assertOk( sub_called );
}, Error );
},
/**
* When a constructor is instantiated conventionally in ECMAScript, the
* instance's `constructor' property is set to the constructor that was