-
Notifications
You must be signed in to change notification settings - Fork 213
Property mixins #1353
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Comments
As I read it, the general effect is to introduce a field (getter, setter and initializer, possibly some more private support stuff for those) through a mixin. The only thing new is that you get to choose the name that the mixed in field is introduced as, so you are really creating a mixin where you abstract over one of the member names. Which is why it's applied to the field declaration instead of the class, so you can specify the field name. (Or, in other words, it's a code template which abstracts over the name.) |
@tatumizer In comparison with Kotlin, you have to specify the field type at the field declaration site, but here the intention is that the type is inferred from the mixin declaration. Due to this the mixin declaration is a bit cluttered, but field declaration isn't. For both examples, without inference: You could also infer the type from the getter and setter, but then the field type of a property mixin isn't easy to see at a glance. Lots of different tradeoffs here. |
@lrhn I think requested effect is larger than that. I would expect that class MyCoolState extends State<MyCoolWidget> with SingleTickerProviderStateMixin {
final _controller with AutoAnimationController;
// Implicit:
// @override
// void initState() {
// super.initState();
// _controller.initState();
// } Am I guessing your intent right @ds84182? |
@mraleph Yes, that's correct. The intent is to match the same behavior as normal mixins while disallowing the introduction of new members. I wouldn't say this desugars to delegations though, consider this example: abstract class SerializationObject {
Map<String, dynamic> serialize() => {};
}
property mixin SerializedProperty<T> for T on SerializationObject {
final String _name;
SerializedProperty(this._name);
T _data;
T get => _data;
set (T value) => _data = value;
@override
Map<String, dynamic> serialize() => super.serialize()..[_name] = _data;
} Because of how One additional thing to explore is whether we can expose a plain field from a property mixin, so the field can be initialized within a constructor. There are some cases, like |
A normal mixin with an If you look at the So, if you instead had a hypothetical "syntactic mixin" where you pass in a name as some kind of parameter, and it then declares a member by that name, instead of using a fixed name, I think you could achieve the same. (Lots of other things will have to be different because of that, for example the mixin cannot have an interface,) |
@tatumizer The point of |
This seems like a job for macros. #1482 |
I don't quite agree with that This proposal seem to be targeting flutter/flutter#51752 and related issues. While we could use macros to implement something similar to what is described in this issue, this would cause a performance downgrade by rebuilding more widgets than necessary. We'd likely need #1874 to solve the rebuild issue, which doesn't seem planed as part of the current macro proposal |
One of the most powerful features in Kotlin is the ability to abstract over properties via delegation to wrapper objects. https://kotlinlang.org/docs/reference/delegated-properties.html
In Kotlin, this allows the reuse of behaviors for getters and setters. Or in Dart terms, it is a mixin that can be applied to an object member. These mixin applications are not like typical mixin applications, since they anonymously "graft" into their targets in an implementation-defined way. They also do not add new members to the class, only overriding existing members or providing new members through property member access.
Real life example of where this would be useful:
The code snippet above solves one of Flutter's pain points, by generalizing the cruft needed for AnimationController setup.
Another example, using arguments and public property fields:
So... Why?
In general, Flutter devs face many issues when dealing with asynchronous resources, or animation controllers, or other disposable objects. There are so many ways to write buggy code, and in many cases the way to write it correctly is non-intuitive. While there are IDE integrations for generating things like animation boilerplate, things like properly handling Futures in a State can lead to bugs if proper mounted checks aren't done, this goes for all asynchronous resources really.
Minimizing the amount of duplicate code and relying on a single implementation helps Flutter developers immensely, and giving developers a library of handy property mixins is a step in the right direction.
cc @rrousselGit, who wrote https://github.com/rrousselGit/flutter_hooks as an alternative way of solving this problem
The text was updated successfully, but these errors were encountered: