-
Notifications
You must be signed in to change notification settings - Fork 213
Add data classes #314
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
No promises, but it's on the radar.. |
Or inline make it shorter?
|
Are there any updates on this enhancement? I'm currently working with Flutter, and having come from the Kotlin/Android world, this is something that would make the transition a lot nicer. Especially when creating ViewModels, or even simple data models, this would make it a lot easier. |
@dcovar don't expect anything short term. It won't be part of Dart 2. |
Community could write a package similar to Lombok who autogenerates code from a valid annotated source code file. One more thing for the wishlist on either flutter/flutter#13607 or flutter/flutter#13834, not sure which |
|
One thing worth mentioning is that data classes and sealed classes can both be viewed as an instance of a metaclass. If enough different kinds of special-cased classes are proposed, at some point it might become better to add metaclass programming to the language, with a few individual cases of syntax sugar. Dart already kind of flirts with the idea when you look at what was needed to make the mirrors API work. |
I support this, but suggest also adding |
@andrewackerman Data classes shouldn't have more than a generic minimum to be used as domain entities, this being |
@i-schuetz Then maybe there can be some optional attributes that can be added to the class declaration so these features can be added for people who need them? Serialization may not be a universal requirement but I'd bet that it would be needed often enough that people would want to at least have the option. Otherwise it would largely defeat the purpose of having a concise data class declaration syntax but then have to manually create the (de)serialization methods. And it's not like it would need to serialize to actual JSON strings. It could serialize to |
Maybe something generic along the lines of Swift's |
I agree with @i-schuetz that adding a |
@leafpetersen @munificent @lrhn – should be moved to the language repo? |
yes, thanks. |
Let's kill the argument that moving to Dart (Flutter) from Kotlin is like moving back in time several years. |
The point of having data classes (apart from immutability) is to have implicit methods e.g. toString(), hash(), == for free. More importantly for immutable class there is a need for mutation method (e.g. Kotlin apply() aka copyWith() in other languages) with default implementation to avoid boilerplate of mutation method. |
Hello, This proposal is great and could attract more developer like me. Do you know when it could be implemented ? |
@benoit-ponsero is the method copy done by reflection? |
It's a compiler generated method. |
Then it must be tree-shaken when built with dart2js. |
Here in our company we are crossing our fingers to get this feature arrive son! |
I'm also hoping that this will be added, a way to have a default implementation of |
For a more lightweight alternative to |
right! there's literally no way to define defaults with a field-first approach. data class Point(int x, int y);
data class User({
required String name,
required String email,
}); at which point the only "opinion" is in making them final or not, which the answer is obviously yes, because otherwise why would it be a data class? |
They are. That's why declaring them as value classes makes total sense. But they must not override ==/hashCode.
It's a chicken-and-egg kind of problem, which is never easy to resolve. One needs to come up with the list of pros and cons for each variant, assign weights, consider statistics of usage, etc.. BIG brainer. :-) |
Well I guess the dart team already has an answer about primary constructors and its syntax here. |
immutability and data classes might be orthogonal concepts AFAIK. |
Also I wanted to address the following; I might not be on the same page as you guys.
AFAIK, no. All the code snippets shared from @orestesgaolin comment (and below, from other folks) are (imho, heavily) opinionated. And I feel this is bad. My 2 cents: we need a good amount of annotations (or an ad-hoc syntax) to handle different needs; also the "just ship something that works for me, and let others make do" argument can't work. Like that, you'd let down a lot of people. Keep in mind that this language is trying to find its space in non-client-side software, meaning it has to look "appetizing" to new folks. Let me summarize the design choices one can make when writing a data class:
I bet we could collect To have a glimpse on how deep the serialization topic alone can be, I suggest taking a look at @schultek RFC proposal; spoilers: it is not just about |
@kevmoo should we open a discussion for this instead? It would reduce the amount of notifications subscribers are getting |
Why? I don't see any reason not to. |
You don't, but the flutter people do! :-) |
@tatumizer Then why define widget as a dataclass? |
Not a dataclass, but a value class. If you need an example of how it really works (in dart and elsewhere), consider a mixin with the mixin MusicalPerformer on Musician {
performerMethod() {
print('Performing music!');
super.musicianMethod();
}
} The meaning of this declaration is: if your class implements The feature that adds the |
If overriding More to the point, value classes could easily get the same identity behavior as records, meaning that they need not have a persistent identity. That would make them ineligible for being a widget unless they override |
There are 2 potential explanations for this:
It's a pure speculation on my part - I might have misunderstood something slightly or even totally 😄 |
Regardless, if we get value classes, it makes total sense for Flutter to make a breaking change and adapt. It wouldn't really impact people anyway. |
It might become a breaking change for anyone currently (naively) using an object as a key to a map. When value classes are introduced, everyone will start changing their de facto value classes to the formal value classes. Who knows what can break. There are 2 cases to be considered:
I'm trying to recall how many times I used non-trivial objects as keys. Probably twice in my entire life. But in these cases. I won't be able to use generated methods anyway - I didn't need all fields, just some of them. Don't get me |
You're not really making much sense here. Most people switching to value classes would do so for classes that already override == and hashcode. If they do so for a class that did not, then perhaps that's a breaking change, and the usual treatment applies. We still have language and package versioning, so if you're natively using an object as a map key that suddenly has == overridden, you'd probably notice. |
How many classes like this are there? I asked chatGPT to list the classes in flutter that override ==/hashCode. There's just a handful of them (like Border, EdgeInsets, Key, Size, Color, etc). I went to API docs to see how these methods are implemented - turns out, automatic generation could handle only half of them. Some use private members, some refer to
Maybe. But then, the generated ==/hashCode will be unused, so why these methods are even there? The whole debate is about whether in the rare cases when the user wants to generate ==/hashCode it would be too taxing for said user to write an explicit annotation requesting the feature? And because of that, we have to shove hashCode/== down everybody else's throat no matter if they want it or not (they don't)? |
I think the core of the issue is that people want what Kotlin does, and I've never ever seen anyone complaining about the way they do equality on data classes. I think there are more than a dozen cases in Flutter, because almost every class that carries a value inside should be a data class. It simplifies so much.
Flutter right now is basically: someone needs equality, or toString, add PR, done. With data classes the question is: is there anything that shouldn't become one?
Examples of future data classes: Size, Offset, Border, BorderSide, RoundedRectangleBorder, EdgeInsets, Rect, Rrect, Radius, TextStyle, Shadow, BoxDecoration, ThemeData, ColorScheme, MaterialStateProperty, Curve, PointerDownEvent, TextSpan, TextRange, TextSection, Key, Locale, AssetBundle, TextInputType, Alignment, DragStartDetails.
|
@tatumizer It's the other way around. Flutter widgets are a rather rare case where classes with a purpose of holding data (config data) shouldn't implement value equality. And even here it's only because the framework wrongly uses 99% of the time I want to have value equality for data classes. It just makes more sense than reference equality. Many languages do it like this. For example: Kotlin ( |
In Kotlin, people don't complain because the concept of data class is not well-defined. Here's the thread I especially like this comment (speaking on the use case of data class) Is that all? Why not annotate the class with
But dart already has record types, exactly with the behavior you expect from data classes. Why do you want to duplicate the concept under a different name? |
Because record types cannot be used as data classes.. they are anonymous. A data class is supposed to be a proper named type, and not to be interchangeable with any other data class that contains the same number of properties with the same types in the same order. Infact, if Dart would allow to give a name to a record type (but a real type name, not just an alias like typedef ) , then we would almost have data classes. Only copyWith would be missing but seems to be coming for records. |
So, you think they also wouldn't complain, if Dart wouldn't implement
Because:
No, Dart only has anonymous records. They are more similar to C#'s tuples than to C#'s records. You are comparing just names instead of implementations. Ironically, that is somewhat similar to reference vs value equality issue ;) Is there any good reason you wouldn't want to have value equality by default for data classes? Since, that would make Dart's data classes different than similar constructs in other languages, the reason would have to be really good. |
I'm saying exactly that Dart should implement that instead of making value class. |
@lucavenir's comment swayed my viewpoint on this topic. There's a lot of opinions in this thread, and each has valid points. But it's not going to be possible for us all to agree here on any one thing. Data classes won't satisfy everyone's needs, but some devs do want them. I think the answer is what's already been said...
With these we still get a good dev experience, we can support any of the opinions stated above because build runner is generalized, and we get data classes if we want them. @equality
@copyWith
@json
class MyData({ int x, @Json(key: 'z') int y }) The dart team is headed in the right direction. |
and then you can have |
sounds like we still want "macros" that said, introspection is a pain |
In Swift, there're some standard protocols (swift's equivalent of interfaces) with the option of autogeneration: Equatable, Comparable, etc. class A overrides Equitable, Stringable {...} There can be a standard DataClass interface1 that combines several interfaces. Footnotes
|
This just looks like it should be a mixin that looks like this: mixin Equatable {
external operator ==(Object other);
external int get hashCode;
}
mixin Stringable {
external String toString();
} Which would be filled in by the compiler because that's exactly what |
Interesting. This idea probably has been considered before and rejected. I wonder why. |
But sure that has been considered explicitly. It's also not a feature that can easily be generalized and made available to users. Which means that only the platform can define these special mixins, and it has to get them right, because they'll be hard to change. (Can still be declared in a package and be versioned, the compiler just needs to recognize all the supported versions. And they'll likely be used so much that a major version increment becomes impossible.) Would Flutter introduce their own magical interfaces? |
For each of these arguments, one can easily come up with a counter-argument. (Actually, you provided some of the counter-arguments yourself).
How are you going to implement data classes then? They are supposed to support the same functionality as the (more selective) mixins in question. The same applies to any feature generated by (using the term loosely) metaprogramming. E.g. if someone provides a generator of toJson (annotation-based), it faces the same problems as jackson, with the same solutions (that is. adding another annotation per week). What is the difference?
These rules can be modified with no harm to anybody. On the surface, the code added to different classes by a mixin even looks identical ( (Further, I would even go as as far as suggesting that the generated (@bivens-dev: if you need any help, please don't hesitate to write to me personally. My email is in my github account). |
Immutable data are used heavily for web applications today, commonly with Elm-like (redux, ngrx, ...) architectures. Most common thing web developer is doing with data is creating a copy of it with some fields changed, usually propagated to the root of state tree. JavaScript has spread operator for this. There should be a easy way to use immutable data structures in Dart. I would like to have data classes (inspired by Kotlin) in Dart. Possible API:
Compiler assumes that all fields of data class are immutable. Compiler adds
equals
implementation based on shallow equals,hashCode
implementation based on mix of all object fields,toString
implementation of the form<Type> <fieldN>=<valueN>
, andcopy
function to recreate object with some fields changed.You may argue that there is already Built value package that allows to do similar things, but we have many issues with package, mainly:
I have found that using built value actually decreases my productivity and I do my work faster with even manually writing builders for classes.
If data classes would be implemented on language level, it would increase developer productivity and optimizations can be made when compiling code to particular platform.
The text was updated successfully, but these errors were encountered: