A strawman for subclassing

David Bruant david.bruant at labri.fr
Wed Jun 15 07:17:39 PDT 2011


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 
> <mailto: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]].


> 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/19b0ee9f/attachment-0001.html>


More information about the es-discuss mailing list