A strawman for subclassing

Mark S. Miller erights at google.com
Wed Jun 15 07:43:28 PDT 2011

On Wed, Jun 15, 2011 at 7:17 AM, David Bruant <david.bruant at labri.fr> wrote:

> **
> Le 14/06/2011 07:04, Mark S. Miller a écrit :
> On Mon, Jun 13, 2011 at 5:08 PM, David Bruant <david.bruant at labri.fr>wrote:
>> Le 14/06/2011 01:24, Allen Wirfs-Brock a écrit :
>> > On Jun 13, 2011, at 3:46 PM, David Bruant wrote:
>> >> Hi,
>> >>
>> >> The subclassing native constructor issue came out several times on the
>> >> list and on the web. However, I do not see a strawman for this. There
>> >> are strawman:array_create and strawman:array_subtypes, but no mention
>> of
>> >> a generic solution.
>> > The <| operator is the proposed solution.
>>  Oh ok, sorry, I hadn't read it yet. Thanks.
>> > Using <|  instances with arbitrary [[Prototype]] values can be created
>> for any type built-in object type that has a literal representation.  that
>> is functions, arrays, regexps, and less interestingly, strings, numbers,
>> booleans.  The resulting instance all have the appropriate special internal
>> behaviors that are associated with the built-in types.
>>  It requires the right-hand side to have a specific initialization
>> syntax. It currently works for all the "classes" you cited ("functions,
>> arrays, regexps, and less interestingly, strings, numbers, booleans"),
>> but does not for the current harmony:simple_maps_and_sets for which
>> there is currently no specific syntax. Consequently, these could not be
>> subclassed (or I am missing something).
>> This would be the case for any other native "class" that wouldn't such
>> syntax. I'm not sure it's is viable in the long term because it will
>> require all subclassable (something people will want to subclass)
>> "classes" to have a syntax.
>> I like the idea of the <| operator, but a generic non-syntaxy solution
>> would be good too in my opinion. It would also allow people to subclass
>> host constructors (host objects with [[Construct]]).
>  We have noticed this issue, and an draft of the classes proposal
> attempted to address it. What's left of that, at <
> http://wiki.ecmascript.org/doku.php?id=harmony:classes#constructor_chaining>
> is:
>   These semantics for constructor chaining preclude defining classes that
> inherit from various distinguished built-in constructors, such as Date,
> Array, RegExp, Function, Error, etc, whose [[Construct]] ignores the
> normal object passed in as the this-binding and instead creates a fresh
> specialized object. Similar problems occur for DOM constructors such as
> HTMLElement. This strawman can be extended to handle such cases, but
> probably at the cost of making classes something more than syntactic sugar
> for functions. We leave that to other strawmen to explore.
> I think that saying "whose [[Construct]] ignores the normal object passed
> in as the this-binding and instead creates a fresh specialized object." is
> misleading. It seems to imply that the internal [[Construct]] method of an
> object always create a "normal object". It is not true. Internal
> [[Construct]] of native functions (ES5 - 13.2.2) create a normal object
> (step 1), but there is no constraints for other objects with an internal
> [[Construct]] to do so.
> Namely, Date, Array, RegExp, Function, Error have a different approach to
> [[Construct]]. Host objects aren't This difference is further emphasis with
> Harmony proxies which have the ability to provide two completely different
> functions to Proxy.createFunction(handler, call, construct).
> By the way, slightly above the paragraph you quote is written:
> "Within the body of the constructor, an expression super(x, y) calls the
> superclass’s [[Call]] method with thisArg bound to this constructor’s this
> and the arguments x and y."
> Why has [[Call]] been chosen over [[Construct]]? The latter makes much more
> sense in the context of inheritance in my opinion. And if I ask "A extend B"
> and B is a function proxy for which I have provided a custom [[Construct]],
> I expect this one to be called, not [[Call]].

As [[Construct]] is currently defined, you can't pass in an already
constructed object for it to further initialize. So it doesn't make sense
for constructor chaining to call the superclass' [[Construct]], even if the
superclass is a function proxy.

>  I continue to believe that it would be valuable to subclass built-ins,
> that classes are a fine place to hang this on, and that it should be
> developed as a separate strawman proposing to extend classes in this way.
> The "something more than syntactic sugar" may be a big impediment to
> adoption of such a strawman, and should rule it out for ES-next. Is there
> some simple limitation we could impose on classes in the ES-next timeframe
> to avoid painting ourselves into a corner, such that we could still consider
> such a strawman for ES-after-next?
> Actually, I think that if what I've said above is considered, built-in
> classes won't be precluded anymore. And the following code would be legit:
> -----
> class SortedArray extends Array{
>   constructor(args){
>     return super(...args); // call Array's [[Construct]]
>   }
>   indexOf(e){
>     // I can do an efficient binary search, because it maintain the
> invariant that my array is sorted
>   }
>   push(e){
>     // Changing push def, because I have to maintain the array sorted.
>   }
>   // ...
>   // .forEach, .filter and other awesome functions are inherited from
> Array.prototype
> }
> var sa = new SortedArray();
> // sa -> SortedArray.prototype -> Array.prototype -> Object.prototype ->
> null
> // sa is a native Array object thanks to the "super" call in SortedArray
> constructor.
> -----
> David

-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20110615/7f347261/attachment.html>

More information about the es-discuss mailing list