New: proposal-class-modifiers
Logan Smyth
loganfsmyth at gmail.com
Mon Dec 3 02:56:46 UTC 2018
> Contrary to what you may have been led to believe, the definition of a
class is its prototype. There are those who refuse to accept this reality,
and that's fine. But if you make the wrong assumptions as a result of an
incorrect understanding, the results won't turn out how you want.
Can you please keep this extremely condescending tone out of these
discussions? I don't know how you expect people to get on board with your
proposals when you constantly imply that those that disagree with you don't
know what they are talking about.
> The constructor only comes into play after a new object has been created
with the corresponding prototype attached.
A prototype with an entirely different constructor is an entirely different
class. The behavior of a constructor is critical to the behavior of an
instance of a class, and in an ideal world is responsible for defining all
of the own properties of the instance. I don't understand how a prototype
on its own could be considered to represent the class as a whole.
> Constructor comparisons can easily be spoofed simply by Proxying the
constructor.
I'm not sure I see how that would be any different for intercepting the
`.prototype` access.
> With `final`, the point is that a `class` that extends from a `final
class` ***cannot be defined***, not simply "cannot be instantiated". Even
without instantiating, a defined `class` can still be used.
I don't disagree that it it would throw as early as possible in an ideal
world, just that it seems to complicate the implementation dramatically
with out a ton of benefit that I can see. I think it does depend on your
overall goal though. Is `final` meant to mean that the prototype may never
exist anywhere but the head of the prototype chain, or just that a subclass
may not be constructed? That I guess goes to Isiah's questions about
`Object.create` and such as well. It seems like 99% of the time I'd be much
more interested in preventing creation of subclasses. I don't particularly
care about the exact location of an object in the prototype chain.
On Sun, Dec 2, 2018 at 6:25 PM Ranando King <kingmph at gmail.com> wrote:
> @Logan
>
> > It would not be good if you could sidestep `abstract` by taking the
> prototype from the class and making a new constructor for it.
>
> That's precisely why it's a prototype test and not a constructor test.
> Everything that defines the initial "shape" of the class is on the
> prototype. The constructor only comes into play after a new object has been
> created with the corresponding prototype attached. If the prototype of the
> constructor being called matches the prototype of newTarget, and that
> prototype has been flagged as abstract, the new object creation is halted
> immediately. Constructor comparisons can easily be spoofed simply by
> Proxying the constructor. Where target would be the un-Proxied constructor,
> newTarget would be the Proxy. They wouldn't match so the abstract test
> would fail and an object would be constructed.
>
> Contrary to what you may have been led to believe, the definition of a
> class is its prototype. There are those who refuse to accept this reality,
> and that's fine. But if you make the wrong assumptions as a result of an
> incorrect understanding, the results won't turn out how you want.
>
> With `final`, the point is that a `class` that extends from a `final
> class` ***cannot be defined***, not simply "cannot be instantiated". Even
> without instantiating, a defined `class` can still be used.
>
> >...it would essentially just be the negation of the check `abstract` was
> doing already.
>
> That's precisely correct. These 2 new tokens are the polar opposites of
> each other. One restricts construction to cases where the prototypes of
> `target` and `newTarget` match (`final`), while the other requires that
> they don't match (`abstract`). That's also the reason they cannot be used
> together.
>
> @Isiah
> Sounds like part of what you're looking for is abstract methods rather
> than an `abstract class`. I wasn't targeting that. If I were, that would be
> something to add to proposal-common-class-modifiers. If I were to look at
> what you're describing more holistically, you're looking for "interface", a
> way to set up a contract for what's supposed to be there and require it all
> to be present. I wasn't targeting that either. In fact, that would probably
> be a good proposal all by itself. I'll give an implementation for that some
> thought. However, with this proposal, all I'm thinking about is inheritance
> constraints.
>
> As for `final`, I need you to convince me that it's worth while preventing
> Object.create and Object.setPrototype. It's shouldn't be that difficult to
> do, but I don't have an understanding of why you'd want to. Especially when
> you consider that when some form of private goes in (assuming it's not
> Symbol.Private) class instances will be quite a bit different than vanilla
> objects.
>
> I get that `final` is something not seen in dynamic languages (outside the
> JVM), but it is a useful tool in giving developers control over how their
> code can be used. Isn't that part of the point of trying to implement
> private data in ES?
>
> On Sun, Dec 2, 2018 at 4:19 PM Isiah Meadows <isiahmeadows at gmail.com>
> wrote:
>
>> @Logan If this helps explain my stance, I'm skeptical of the use, and
>> it really disrupts the consistency of JS's object model quite a bit.
>> It makes sense to enforce at a static level, but not really at a
>> dynamic runtime level. Also, this is lacking precedent in other
>> dynamic languages with classes: Python, Ruby, Smalltalk, Lua, Io, and
>> pretty much every other dynamic language with class- or
>> prototype-based inheritance (that wasn't made for the JVM) doesn't
>> support final classes. Python (IIRC through a decorator) and Ruby
>> support abstract methods, but not final classes/methods.
>>
>> -----
>>
>> Isiah Meadows
>> contact at isiahmeadows.com
>> www.isiahmeadows.com
>>
>> On Sun, Dec 2, 2018 at 5:10 PM Logan Smyth <loganfsmyth at gmail.com> wrote:
>> >
>> > Wouldn't it be better `abstract`'s `target.prototype ===
>> newTarget.prototype` check to be `target === newTarget`? It's not really
>> the prototype that is at issue here, it is the class constructor itself. It
>> would not be good if you could sidestep `abstract` by taking the prototype
>> from the class and making a new constructor for it.
>> >
>> > For `final` is it worth throwing an `extends` time vs just throwing
>> when the class is instantiated? It seems like `final` would otherwise
>> require new private state on the constructor itself, where otherwise it
>> would essentially just be the negation of the check `abstract` was doing
>> already.
>> >
>> > Also, if those make sense, what do we gain by having these be keywords
>> instead of decorators?
>> >
>> > On Sun, Dec 2, 2018 at 1:43 PM Isiah Meadows <isiahmeadows at gmail.com>
>> wrote:
>> >>
>> >> For `abstract`, I could see that being three things:
>> >>
>> >> - Throw a reference error if an abstract method is called with no
>> concrete implementation
>> >> - Throw a type error if the constructor is called without its abstract
>> methods implemented
>> >> - Throw a type error if a subclass fails to implement all remaining
>> abstract methods and is not itself abstract
>> >>
>> >> Each of these could be reasonably tacked on at the end.
>> >>
>> >> For `final`, you'll need to create a way to block all means of
>> `Object.create`, with class constructors being the sole exception. That
>> complicates the mechanism tremendously, since prototype-based inheritance
>> alone can't enforce this unless you make `Object.setPrototypeOf(obj,
>> parent)` no longer directly equivalent to `obj.[[Prototype]] = parent`.
>> >> On Sun, Dec 2, 2018 at 16:28 Ranando King <kingmph at gmail.com> wrote:
>> >>>
>> >>> Object.create and Object.setPrototypeOf operate on a different level
>> than what I'm targeting. I can conceive of a means to make even these
>> functions respect these tokens. However, if I were going to do that, I'd
>> want these tokens to be applicable to objects and functions directly.
>> Reflect.construct is essentially part of the process for `new` and would be
>> required to respect these tokens. I'm still open on how far the effect of
>> these tokens should extend.
>> >>>
>> >>> On Sun, Dec 2, 2018 at 3:20 PM Isiah Meadows <isiahmeadows at gmail.com>
>> wrote:
>> >>>>
>> >>>> How would this interop with `Object.create`, `Reflect.construct`,
>> and `Object.setPrototypeOf`?
>> >>>> On Sun, Dec 2, 2018 at 16:16 Ranando King <kingmph at gmail.com> wrote:
>> >>>>>
>> >>>>> This proposal is intended to add `abstract` and `final` to `class`
>> definitions so as to modify the inheritability of a class.
>> >>>>>
>> >>>>> https://github.com/rdking/proposal-class-modifiers
>> >>>>> _______________________________________________
>> >>>>> es-discuss mailing list
>> >>>>> es-discuss at mozilla.org
>> >>>>> https://mail.mozilla.org/listinfo/es-discuss
>> >>
>> >> _______________________________________________
>> >> es-discuss mailing list
>> >> es-discuss at mozilla.org
>> >> https://mail.mozilla.org/listinfo/es-discuss
>>
>
-------------- next part --------------
An HTML attachment was scrubbed...
URL: <http://mail.mozilla.org/pipermail/es-discuss/attachments/20181202/6425bd08/attachment.html>
More information about the es-discuss
mailing list