-
Notifications
You must be signed in to change notification settings - Fork 113
Reflection from superclasses #36
Comments
I think the only way this could be done is with a new feature (ie, a new proposal separate from this one) for a class "finisher" function, that you could define on |
That could work if each class (and of particular interest here, each child/parent class) had its own "finisher" function. That way the parent class could do some initialization based on reflection before the rest of the child constructor (the code after If someone remembers off the top of their head, can you point me to where in previous discussions the timing of field definition/initialization was discussed? I noticed that there's already a concept of "finishers" in the decorators proposal, which I need to look into in more detail...if that could be expanded to the class level, maybe my goal could be accomplished with syntax as simple as:
(I realize this isn't the right place for extended discussion about decorators, so I'm happy to move the decorator discussion to that repo instead if more detailed discussion is warranted.) |
I don't quite understand why you want to do this by subclassing. If you'd be OK calling out to a function to do the assignments, it would be as easy as: function assign(target, attributes) {
for (let key of Object.keys(attributes)) {
if (Object.hasOwnProperty(target, key)) {
target[key] = attributes[key];
}
}
}
class Cat {
name;
curious = true;
constructor(attributes) {
assign(this, attributes);
}
} What's the motivation for having this logic in the superclass? |
There are two main things I'm thinking about here:
One of the purposes of reflection is to be able to access compile-time information at run-time (or at least, this is common in other languages...in some languages you can even access the comments above a class or function via reflection). It's difficult to anticipate all the useful ways that reflection could be used, so I would generally prefer access to more information rather than less. As soon as a class declaration has been interpreted, it would be logical to be able to access metadata about that class, including its instance field declarations, via reflection. With objects (as opposed to classes) it's trickier, since the properties don't exist on the object until they've been assigned to This is a philosophical argument of course, and off the top of my head I can't think of any cases other than the one I presented above where being able to reflect on subclass fields from a parent constructor would be useful. So if there are technical arguments against supporting this, then I suppose the technical arguments should trump the philosophical argument. Regarding
Or if a subclass made more sense for some reason, then as an alternative to a standalone utility method, this could also work:
It's sounding more and more like this use case shouldn't, in and of itself, motivate any change in the current proposal for class fields. It does seem relevant to this proposal and worth discussing, and it's an example of using reflection from a parent constructor - those are the reasons I brought it up. It's of course a common pattern for a constructor function to accept an object containing the initial state...models in Backbone, Ember, Breeze.js etc. support support this in various ways. I just found a library called ObjectModel, which comes the closest to the particular usage I had in mind with my example: It also has an interesting approach for use with ES6 classes: My main goals are simplicity and avoiding boilerplate code in cases where it would be very common. |
OK, it sounds like, between decorators, expressing this functionally, and possibly inheriting from a class whose constructor does all the work (as in that library--then, you would just not use the class fields feature), this problem is solved. If you want to follow up in the decorators repository, that could be good, but I don't really see any missing features there. |
I agree; I consider that this has been considered ;) and the current implementation options are sufficient for my example. I will explore the latest version of the decorators proposal in more detail and follow up there if warranted. I still think |
For context, @wycats previously proposed a full reflection API for fields, but I objected to it because such APIs might give too much flexibility to monkey-patch existing things and give a high implementation burden. |
Would it be possible for this proposal to include support for reflection over instance properties from a constructor in a superclass? This would be very useful to support something like named constructor parameters, as described in #33. Here's the example again (somewhat modified for clarity for this new thread):
My current understanding of the class fields proposal is that the definition of
Cat
here would be equivalent to:Assuming that's the case, then assigning property values in the
Entity
constructor wouldn't work, since the property isn't defined until after the call tosuper()
. My initial thought was that putting the properties on the prototype in addition to the instance would solve this, but I understand now that this causes too many other issues. But I think there should still be a way to accomplish something like the above, as can be done in other languages like PHP and Java (and probably others).For this particular example, decorators might provide an alternative solution, since decorators are evaluated early on, e.g.:
(Note: I'm making several assumptions here about the interaction between classes and decorators that I don't think are finalized yet since decorators are still in stage 2.)
Still, I imagine there are other situations where it would be useful to use
Object.getOwnPropertyNames
orReflect.ownKeys
from a superclass and have it include the names of instance properties defined in a child class.But
Object.getOwnPropertyNames
should be semantically correct, and not return properties that don't exist yet...so I suppose what I'm really proposing is that class fields should be evaluated like this:...which of course wouldn't be valid JS if actually written that way (since you can't reference
this
before callingsuper()
), but would it be feasible for class fields to work this way behind the scenes? If not, maybe there could be a new reflection method that would mean something like, "tell me the names of properties declared in my class or any of my subclasses, regardless of whether or not they've been initialized yet".Sorry for the somewhat meandering description; I was trying to cover various considerations and I hope it wasn't confusing.
The text was updated successfully, but these errors were encountered: