0

In Dart, I have a class like this that protects _x behind getters/setters which allows me to control changes to _x:

//in a.dart
class A {
  int _x;
  int get x => _x;
  set x(int value) {
    bool validation_ok=true;
    //do some validation/processing
    if (validation_ok) {
      _x = value;
      //perform side effects that should happen every time _x changes e.g. save to SharedPreferences
      print('Validated $value and side effects performed');
    }
  }
}
//in amain.dart
import 'a.dart';
void main() {
  A a = A();
  a.x = 5; //if validation successful stores 5 to _x and performs side effects
  print(a.x); //prints 'Validated 5 and side effects performed' and then '5'
}

But what can I do if instead of an int, I want to protect a List or an object?

//in b.dart
class B {
  List<int> _y;
  List<int> get y => _y;
  set y(List<int> value) {
    bool validation_ok=true;
    //do some validation/processing
    if (validation_ok) {
      _y = value;
      //perform side effects that should happen every time _y changes e.g. save to SharedPreferences
      print('Validated $value and side effects performed');
    }
  }
}
//in bmain.dart
import 'b.dart';
void main() {
  B b = B();
  b.y = [5]; //if validation successful stores [5] to _y and performs side effects
  print(b.y); //prints 'Validated [5] and side effects performed' and '[5]'
  b.y.add(6); //now _y is [5,6] but no validation was done on 6 and no side effects performed
  print(b.y); //prints '[5,6]' only
}

Notice that in bmain.dart the line b.y.add(6) adds to the private list without going through the setter. How can I ensure no such access is permitted and any changes to the private list or object are controlled?

iBob101
  • 1,460
  • 3
  • 14
  • 20

1 Answers1

2

You cannot expose a mutable object and be certain that it's not changed by someone else. That leaves your options as:

  • Not exposing the object at all.
  • Exposing a view of the object which does not allow modification.

The former is not as bad as it sounds. If you give your container class members which accesses the members of the protected object, then you don't have to expose the object itself. (It might even be a good idea, q.v. "the law of Demeter").

The latter would mean wrapping the real object in a view adapter which throws if you want to make changes. For a List, you can use an UnmodifiableListView. For other classes, you might need to write one yourself. This solution is obviously only skin deep. Code with access to the unmodifiable list cannot change which objects are elements of the list, but if those objects are themselves mutable, then they can be changed as well. Usually protecting the list itself is what you need.

lrn
  • 64,680
  • 7
  • 105
  • 121