[Flutter]美術館に例えて、ゲッターを語る


ゲッターとは

ゲッター(Getter)は、あるクラスの情報を読み取るためのメソッドです。具体的には、ゲッターはクラスの内部状態やプライベートなデータを外部から安全にアクセスするための手段を提供します。

例えば下記のコードです。

class NavigationController {
  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

  GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;
}

上記のコードが理解できない方、安心してください。僕も分かりませんでした。その方の為に、美術館を例えにして説明してみました。
それでも分からなかったら・・・すいません。どこら辺が分からなかったかをコメントしてもらえれば補足しますね。
それでは、最後までお付き合いください。

美術館に例えて、ゲッターを語る

美術館には多くの貴重な芸術作品が展示されていますが、これらの作品は直接触れることができません。代わりに、美術館は作品を安全に鑑賞できるように展示ケースや展示スペースを提供します。ここで、展示されている芸術作品はクラスの内部データに相当し、美術館が提供する展示ケースやスペースはゲッターに相当します。

訪問者(クラスの使用者)は展示ケース(ゲッター)を通して芸術作品(内部データ)を見ることができますが、直接触れたり変更したりすることはできません。このように、美術館は作品の安全を保ちながら、訪問者に作品を鑑賞する機会を提供します。

美術館の例えをコードに起こしてみる

美術館の例えに基づいて、ゲッターのコードを作成してみます。
ArtGalleryクラスを作成し、このクラスが美術館とします。この美術館には、ArtPieceという名前の貴重な芸術作品がありますが、これは外部から直接アクセスできないようにプライベートな状態とします。代わりに、訪問者(クラスのユーザー)がこの作品を「見る」ために、ゲッターメソッドを提供します。

class ArtGallery {
  // 芸術作品はプライベートなプロパティです
  String _artPiece = "モナ・リザ";

  // ゲッターメソッドで芸術作品を安全に提供します
  String get artPiece => _artPiece;
}

void main() {
  // 美術館(ArtGalleryクラス)のインスタンスを作成
  var gallery = ArtGallery();

  // 訪問者はゲッターを通じて芸術作品(_artPiece)を「見る」ことができます
  print("芸術作品を見る: ${gallery.artPiece}");
}

このコードでは、_artPieceArtGalleryクラスのプライベートなプロパティ(貴重な芸術作品)です。外部のコード(この場合はmain関数)は、artPieceというゲッターメソッドを通じてこの作品に「アクセス」できますが、それを直接変更することはできません。これは、美術館の訪問者が展示ケースを通じて作品を鑑賞できますが、それを手に取ったりすることはできない状況に似ています。

美術品を触れようとすると怒られるコード

上記のArtGalleryクラスに基づいて、プライベートなプロパティ(_artPiece)に直接アクセスしようとするエラーを引き起こすコードを作成します。プライベートなプロパティへの直接アクセスはエラーが発生します。

class ArtGallery {
  String _artPiece = "モナ・リザ";

  String get artPiece => _artPiece;
}

void main() {
  var gallery = ArtGallery();

  // エラー:プライベートプロパティに直接アクセスしようとしている
  print("芸術作品に触れる: ${gallery._artPiece}");
}

このコードの最後の行で、gallery._artPieceに直接アクセスしようとしています。Dartでは、アンダースコア(_)で始まるプロパティやメソッドはプライベートと見なされ、その定義されているライブラリ(この場合は同じファイル)外からはアクセスできません。したがって、この行はコンパイルエラーを引き起こします。

プライベートではないプロパティは書き換えられる

アンダースコアを取り除くことで、プロパティはもはやプライベートではなくパブリックとなり、クラスの外部から直接アクセスすることが可能になります。
プロパティがパブリックであれば、そのプロパティの値を外部から変更することが可能です。つまり、artPiece プロパティがパブリック(アンダースコアがない)であれば、その値を「モナ・リザ」から別のものに変更することができます。

以下は、ArtGallery クラスの artPiece プロパティの値を変更するコードの例です。

class ArtGallery {
  String artPiece = "モナ・リザ";
}

void main() {
  var gallery = ArtGallery();

  // 元の芸術作品を表示
  print("元の芸術作品: ${gallery.artPiece}");

  // 芸術作品を変更
  gallery.artPiece = "偽物のモナ・リザ";

  // 変更後の芸術作品を表示
  print("変更後の芸術作品: ${gallery.artPiece}");
}

このコードでは、ArtGallery インスタンスの artPiece プロパティの値を「モナ・リザ」から「偽物のモナ・リザ」に変更しています。これは、美術館に展示されている作品が誰でも自由に変更できる状況に例えられます。このような状況は、実際の美術館では望ましくないですが、プログラミングの世界では、パブリックプロパティの値を自由に変更することが一般的です。

偽者にすり替えようとすると怒られるコード

では、プライベートプロパティを書き換えようとしてみましょう。

class ArtGallery {
  // プライベートプロパティ
  String _artPiece = "モナ・リザ";

  // ゲッターを使ってプライベートプロパティの値を公開
  String get artPiece => _artPiece;
}

void main() {
  var gallery = ArtGallery();

  // プライベートプロパティの値を表示
  print("展示されている芸術作品: ${gallery.artPiece}");

  // エラー:プライベートプロパティは外部から変更できない
  gallery._artPiece = "偽物のモナ・リザ"; // この行はエラーを引き起こします
}

このコードでは、_artPiece プロパティは ArtGallery クラスの外部からは直接アクセスや変更ができません。ゲッター artPiece を通じて、このプロパティの値を読み取ることはできますが、プロパティ自体を変更することは不可能です。

このようにプライベートプロパティを使用することで、クラスの内部状態を外部からの不正な変更から守ることができます。これは、美術館で展示されている作品が、保護のために一般の人々から触れられないようになっている状況に似ています。訪問者は作品を鑑賞できますが、直接触れたり変更したりすることはできません。

最初に振り返る

最初に見たコードが下記です。

class NavigationController {
  final GlobalKey<NavigatorState> _navigatorKey = GlobalKey<NavigatorState>();

  GlobalKey<NavigatorState> get navigatorKey => _navigatorKey;
}

_navigatorKeyというように、プライベートプロパティとなっていますね。
そして、ゲッターを使い_navigatorKeyを見たいなら、navigatorKeyを使ってねっと書かれていますね。
そもそもGlobalKeyとは、何者なのか。という点については今回は触れません。今回は、ゲッターについて焦点を絞っている為です。

結論

・ゲッター(Getter)は、あるクラスの情報を読み取るためだけのメソッドです。(美術館で言う展示ケース)
・ゲッターはクラスの内部状態やプライベートなデータを外部から安全にアクセスするための手段です。
・ゲッターを使う際は、プライベートプロパティにすることもお忘れなく。

最後に

少しでも分かりやすく説明しようと書き始めたら、かなりの量になりました。同じことを何度も書いている箇所もありますが、私の経験から、同じ情報でもその場所に書かれていると集中力が高まり、理解が深まると考えています。
少しでも理解の助けになれば幸いです。
ありがとうございました。

この記事が気に入ったらサポートをしてみませんか?