A strawman for subclassing
Mark S. Miller
erights at google.com
Wed Jun 15 09:11:25 PDT 2011
On Wed, Jun 15, 2011 at 8:17 AM, David Bruant <david.bruant at labri.fr> wrote:
> Le 15/06/2011 16:43, Mark S. Miller a écrit :
> 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
>>> >> 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 <
>> 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.
> Hmm... I think that it's because most current [[Construct]] (ES5 - 13.2.2)
> have steps 1 and 9-10. As far as I know, on ES5, [[Construct]] is only used
> in the "new" operator; Would it make sense to move steps 1, 9 & 10 to the
> "new" operator definition (ES5 - 11.2.2)? The object would be passed as the
> 'this' binding of [[Construct]]. It would allow to create different objects
> on step 1 depending on context (for instance if the constructor has been
> created in a "class"-syntax defintion, the object may inherit from something
> else than Object.prototype). I don't think it would affect how the "new"
> operator currently works.
> Now that I think about it, there is a weird difference between [[Call]] and
> [[Construct]]. The former has a 'this' binding and the latter doesn't.
> Considering the object being constructed as a 'this' binding to
> [[Construct]] could allow what you said ("pass in an already constructed
> object for it to further initialize") by passing the same 'this' object to
> several [[Construct]].
> Does this change sounds feasable?
I think some such refactoring would be feasible and desirable, and is the
kind of refactoring I had in mind when I said
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.
But the refactoring would need to be a bit different than what you suggest,
in order to both maintain compat with current behavior while also allowing
subclassing-with-constructor-chaining to, for example, Date. Please propose
> Regardless of this change, I think I understand that there is some issue
> with wanting a class syntax and inheriting from built-in/host constructors.
> Not because of [[Construct]], but because of the custom Meta Object
> Programming contract.
-------------- next part --------------
An HTML attachment was scrubbed...
More information about the es-discuss