Skip to content

Feature request: getters that return an immutable value #3330

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
stephane-archer opened this issue Sep 7, 2023 · 6 comments
Closed

Feature request: getters that return an immutable value #3330

stephane-archer opened this issue Sep 7, 2023 · 6 comments
Labels
feature Proposed language feature that solves one or more problems

Comments

@stephane-archer
Copy link

stephane-archer commented Sep 7, 2023

I would be able to have getters that return an immutable value and create a compile error with the following code

class MyValue {
  int _value;

  MyValue(this._value);

  int get value => _value;

  void increment() {
    _value++;
  }
}

class MyClass {
  MyValue _myValue = MyValue(42);

  MyValue get myValue => _myValue;
}

void main() {
  final myObject = MyClass();

  print(myObject.myValue.value); // Access the value through the getter, prints: 42
  myObject.myValue.increment();  // Call the increment method
  print(myObject.myValue.value); // Access the modified value, prints: 43
}

Here is a possible syntax:

immutable MyValue get myValue => _myValue;
@stephane-archer stephane-archer added the feature Proposed language feature that solves one or more problems label Sep 7, 2023
@eernstg
Copy link
Member

eernstg commented Sep 7, 2023

Cf. #1518, quite similar.

@leafpetersen
Copy link
Member

I don't understand what the request is, can you be more precise? The code you write there behaves precisely as you describe now. Where do you want a compile error? On the definition of the myValue getter? On the call to increment?

@stephane-archer
Copy link
Author

Sorry for not being clear, I will try to re-explain.
In the example, MyClass has no control over who is modifying _myValue, it's his internal state and this totally breaks encapsulation in my opinion.
I did not create a setter in MyClass yet Everybody who has access to MyClass can modify _myValue by calling myObject.myValue.increment(); for example.
but I would like myObject.myValue to be "read-only", to be able to force that constraint so others (or my future self) to not be able to call myObject.myValue.increment(). If I was in C++ my getter would return a "const ref".
Today the only solution I found is to make the getter return a copy of MyValue so myObject.myValue.increment(); would have no effect on _myValue.
Does this make more sense?

@leafpetersen
Copy link
Member

Why does this not do what you want:

abstract interface class ReadableMyValue {
  int get value;
}

class MyValue implements ReadableMyValue {
  int _value;

  MyValue(this._value);

  int get value => _value;

  void increment() {
    _value++;
  }
}

class MyClass {
  MyValue _myValue = MyValue(42);

  ReadableMyValue get myValue => _myValue;
}

void main() {
  final myObject = MyClass();

  print(myObject.myValue.value); // Access the value through the getter, prints: 42
  myObject.myValue.increment();  // Static error here
  print(myObject.myValue.value); // Access the modified value, prints: 43
}

@stephane-archer
Copy link
Author

@leafpetersen This is doing exactly what I want. I didn’t know you could do that, thanks 🙏.
The only issue I see with this solution is that for every getter you have to create or modify an interface.
adding the const keyword on the return type in other languages is more convenient.

@leafpetersen
Copy link
Member

const keyword on the return type in other languages is more convenient.

Yep. It's a big lift to figure out what the semantics of that should be. In the meantime, read only interfaces get you a fair distance.

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