August 31, 2022

DartでPublic getter, Private setter

Dartには言語レベルでgetter, setterが用意されていて、それぞれget set をつけるとgetter, setterとして扱われます。
シンプルにgetterもsetterもpublicな場合は当然このようになります。

class User {
  String? name;
}

privateなプロパティにしたい場合は_をつけてあげて、public用のgetterを定義します。

class User {
  String? _name;
  String? get name => _name;
}

_nameはprivateになっていて値を代入できないため、なにか特殊な操作をしたい場合はpublicなsetterを用意します。

class User {
  String? _name;
  String? get name => _name;

  set name(String? value) {
    name = value?.isNotEmpty ?? false ? value : null;
  }
}

getterはpublicにしつつ、setterをprivateにしたい場合は、 このようにsetterの名前に_をつければ良い気がしますが、このように書くことはできません。

class User {

  String? _name;
  String? get name => _name;

  // NG
  set _name(String? name) {
    _name = name?.isNotEmpty ?? false ? name : null;
  }
}

その場合はこんな感じで名前をつけることが多い気がします。

class User {

  String? _name;
  String? get name => _name;

  void _updateName(String? name) {
    _name = name?.isNotEmpty ?? false ? name : null;
  }
}

この書き方でも問題はないのですが、やはりnameに対するsetterという意味は薄れてしまいます。
(Documentなどがないとコードからは更新時にこの関数を呼ぶ強制力が生まれない)
ただし、前述の通りこのままではprivateなsetterは作れません。 この場合は若干微妙な気がしますが、_を2つつけてprivateなプロパティを定義します。

class User {

  String? __name;

  set _name(String? value) {
    __name = value?.isNotEmpty ?? false ? value : null;
  }

  String? get name => __name;
}
void main() {
  final user = User();

  final name = user.name; // OK
  user._name("akira"); // NG
}

実質独自のupdateメソッドを作っていることとやっていることは変わりませんが、privateなsetterを作れたのでドキュメントがなくてもコードで意図を伝えられるようになったのかなと思います。

© AAkira 2021