Skip to content

[Feature Request] Syntactic sugar for initializing instance variables inside the primary constructors #2350

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

Closed
ghost opened this issue Jul 20, 2022 · 5 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@ghost
Copy link

ghost commented Jul 20, 2022

So as of Dart 2.17, we can use super initializers inside the constructors. This reduces the code needed for classes that inherit from other classes and simplifies the code.

Since we're going in that direction, I wanted to bring up an interesting feature that Kotlin has which makes defining classes, especially record classes, a lot easier and simpler.

In Kotlin, you can initialize instance variables inside the primary constructors themselves, eliminating the need for the lines of code needed to define the variables first. Kind of like this:

class Person(val firstName: String, val lastName: String, var age: Int)

Can this feature be added to the language? As in making it possible to define classes like this for example:

class ClassyNote extends Note { ClassyNote(super.title, super.content, final Color color, final Icon icon, var Category category); }

@ghost ghost added the feature Proposed language feature that solves one or more problems label Jul 20, 2022
@Levi-Lesches
Copy link

Duplicate of #314?

@ghost
Copy link
Author

ghost commented Jul 20, 2022

Duplicate of #314?

Hmmmm, not exactly maybe? We can already use the required and final keywords to define the parameters for the constructors and then assign them to our instance variables, but if we don't assign it to anything, it will be lost and we won't be able to access it.

What I'm proposing is for this feature to be available without the class necessarily being a data class. Maybe another keyword that signals to the compiler to generate the field instead of letting it be lost. Although I can see how that can get pretty messy and confusing. Another way to go about it would be to deprecate "this.variable" in the next major release of Dart in favor of the feature that enables the same keywords ("required final String name" for example) to generate the fields this time.

If we go with making up a new keyword, it would get kind of messy and polluted in the constructors but we can do it without waiting for the next major release. If we go with the second option, I'd assume it would get confusing for those who already use "required final variable" in their constructors to unlearn the previous meaning (even though most of us use this.variable most of the time). Maybe we should wait for the issue you mentioned to be closed first, and then move on to bringing basically the same feature for variables to other classes that are not necessarily records/data classes?

@vxern
Copy link

vxern commented Jul 26, 2022

Since we're going in that direction, I wanted to bring up an interesting feature that Kotlin has which makes defining classes, especially record classes, a lot easier and simpler.

Kotlin does not have named constructors. Dart does. How would the Dart analyser cope with multiple constructors that each could end up having different signatures? Depending on the constructor used, the created object could end up having different properties to objects created using other named constructors. This is clearly a huge no-no.

class ClassyNote extends Note {
    ClassyNote(super.title, super.content, final Color color, final Icon icon, Category category);
}

This would only work if the class was absolutely tiny. Otherwise, it only aids in the obscuring of the defined fields within a class. I cannot imagine this would be scalable in a non-data class. Also: How would one go about documenting these fields?

@ghost
Copy link
Author

ghost commented Jul 26, 2022

Kotlin does not have named constructors. Dart does. How would the Dart analyzer cope with multiple constructors that each could end up having different signatures? Depending on the constructor used, the created object could end up having different properties to objects created using other named constructors. This is clearly a huge no-no.

Kotlin doesn't have named constructors, but it does have secondary constructors which do the same job as Dart's named constructors. The way they work is that they delegate to the primary constructor (more info on how it's done here) which can easily be done in Dart too. We could use this.variableDefinedInPrimary in those named constructors or simply delegate like so: this.named(firstVariable, secondVariable) : this(firstVariable) {}

This would only work if the class was absolutely tiny. Otherwise, it only aids in the obscuring of the defined fields within a class. I cannot imagine this would be scalable in a non-data class. Also: How would one go about documenting these fields?

Kotlin has been doing this for a while now and it hasn't obscured fields in anyway if you ask me. As for documentation, they can be either documented with a single line inside the constructor, or in the class' documentation. If the field needs a lot of documentation, you can define that single variable, or the whole class if that's easier to read for you, normally and without defining variables inside the class' primary constructor. Even in Kotlin, it's a feature that you can use if you see fit, otherwise you can go about it like how you would normally. But the feature being there is a definite plus in my opinion, weather you use it in certain more complex classes or not!

@leafpetersen
Copy link
Member

We're tracking this feature request here, so closing this in favor of that issue. Let me know if I've missed something about this request that isn't covered there.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
feature Proposed language feature that solves one or more problems
Projects
None yet
Development

No branches or pull requests

3 participants