Explicit backing fields #430
Replies: 7 comments 21 replies
-
It's good to see that this issue has not been forgotten and I think it is very important. I would like to re-iterate that this topic isn't limited to getters (even though the solution described in the KEEP seems to focus on them); it's about setters (and the types they accept) as well. It is one of the most annoying and frustrating limitations in Kotlin right now that I cannot express this: private var user: String
set(user: String) { field = user }
set(user: User) { field = user.username } There are countless examples in DSLs and otherwise where this would be extremely helpful. Since we're decoupling the backing field type from the "public" type, I would propose to take this into consideration as well. In Java, this has always been possible via regular setter overloading and it was a frequently used pattern. Kotlin properties lack this type of flexibility at the moment. There's this issue on YouTrack which was created 11 (!) years ago. The issue links to the former discussion (#278) and the discussion links again back to the YouTrack issue. It's going in circles. Please, Jetbrains 🙏 It's nothing fancy, but this is really needed. |
Beta Was this translation helpful? Give feedback.
-
Having skimmed through the new proposal, it left me a little confused. Illustration to the issue:
Suggestion:
|
Beta Was this translation helpful? Give feedback.
-
I I understand well, defining field uninitialized and initialize it in the class SomeViewModel : ViewModel() {
val city: LiveData<String>
field: MutableLiveData<String>
init {
city = MutableLiveData()
} Is there a reason (or oversight) for this exception? I suppose that, for simple cases, it is still possible to write: |
Beta Was this translation helpful? Give feedback.
-
Not supporting non-private fields is quite disappointing to me, and I don't see a particular rational why not to include it. There's a number of use-cases already listed in the doc, and the only reason not to support it given is
I don't think the ability to write public val city: LiveData<String>
protected field = MutableLiveData() is particularly "implicit" or "magical", especially when you can already do the same for getters and setters. In fact, supporting |
Beta Was this translation helpful? Give feedback.
-
Could the proposal clarify its stance on: val city: StateFlow<String>
field = MutableStateFlow("")
get() = field.asStateFlow() The proposal seems to imply this isn't supported (there is no example with both a As a user, I would find very surprising if this wasn't supported (it means this new feature is incompatible with the existing features). If it is supported, I don't understand why the About the use-case itself: at least in the codebases I've worked on, when I use the backing property pattern, it is much more common that the aim is to expose a read-only wrapper than just upcast the value. If this use-case is not supported, most backing property usages will not change, which decreases the usefulness of this feature a lot. |
Beta Was this translation helpful? Give feedback.
-
From a design perspective I'm not sure that the right approach is to see this as an application of smart casts (even though most of the underlying reasoning applies). While this may simplify implementation in the short term it may make the longer term evolution (to some of the other desired features) difficult. Maybe a consideration of the restrictions would be good instead:
Fundamentally the issue is that in properties the field is not only private, it is hidden except in the getter/setter - separately its type must be the same as the interface (getter). This could be addressed by making the field addressable in either of three ways:
While the currently proposed restrictions for case 3 could perhaps be loosened a bit they will always be "restrictive". This means that either solution 1 or 2 must be used. Solution 1 will always be available. Solution 2 would need to be added to the language. It has two drawbacks:
|
Beta Was this translation helpful? Give feedback.
-
Unfortunately, the following example from "§ Call from inline functions" won't work:
It will, but that's a current bug in the compiler (see KT-7972): |
Beta Was this translation helpful? Give feedback.
Uh oh!
There was an error while loading. Please reload this page.
Uh oh!
There was an error while loading. Please reload this page.
-
This is a discussion of the "Explicit backing fields" feature. The text of the proposal can be found here.
The proposed feature addresses the request KT-14663 "Public and private type for the same property".
With proposed changes, this can be achieved by declaring property field type explicitly, which allows to automatically provide smart casts to field types in calls within the private scope.
Summary of changes for those familiar with previous versions of the proposal:
MutableLiveData
+LiveData
,MutableStateFlow
+StateFlow
), while rejecting support for more comprehensive ones (likeMutableStateFlow
+asStateFlow()
wrapper)asStateFlow()
wrapper is cached instead of calculating on each call), serialization challenges, poor composability and unclear overload resolution rulesBeta Was this translation helpful? Give feedback.
All reactions