Getter Setterについて調べると、
メンバ変数に別classからアクセスする際は Getter Setter を用いるように書かれてたりするのですが、
Getter / Setter 共にpublicでSetの際のチェックが不要な場合、Getter / Setter を使うことにどのような利点があるのか教えていただきたいです。
分からない
C#
1class ObjectPosition 2{ 3 //このGetter Setter はなぜ必要なのか public変数と何が違ってどのような利点があるのかわからない 4 public Position CreatePosition 5 { 6 get; 7 set; 8 } 9} 10
分かる
外部から値を見られても外部から値を変えられたくない
C#
1class ObjectPosition 2{ 3 public Position CurrentPosition 4 { 5 get; 6 private set; 7 } 8} 9
値を変える前にその値に問題ないかチェックしたい わかる
C#
1class ObjectPosition 2{ 3 private string objectName; 4 public stringObjectName 5 { 6 get 7 { 8 return objectName; 9 } 10 set 11 { 12 if (value == objectName || value.Length ==0) 13 return; 14 objectName = value; 15 } 16 } 17} 18
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
回答6件
0
ベストアンサー
一番の理由は、公式のプログラミングガイドでそうするよう言われているからです。
通常、フィールドは、プライベートまたは保護されたアクセシビリティを持つ変数に対してのみ使用します。 クラスからクライアント コードに公開するデータは、メソッド、プロパティ、およびインデクサーを使用して提供する必要があります。
更にその理由の一つが次に書かれています。
これらの構成要素を使用して、内部フィールドに間接的にアクセスすることで、無効な値が入力されることを防止できます。
また、公式情報ではありませんが、多くの有識者から信頼されている次のサイトではこう書かれています。
通常、内部の実装がどうなっているのかを隠蔽(要するに private にする)し、可能な操作のみを公開(public)することが望ましいとされています。 簡単に言うと、メンバー変数はクラス外部から直接アクセス出来ないようにして、オブジェクトの状態の変更はすべてメソッドを通して行うべきだということです。
つまり、プロパティはインターフェースであり、フィールドは実装であり、実装は隠蔽してインターフェースを公開すべきというオブジェクト指向の基本的な考えに基づくものです。
(この場合のインターフェースは Interface キーワードで宣言されるもののことではなく、オブジェクト同士の通信に使うものという意味合いで使用しています)
実装を隠蔽することにより、インターフェースはそのままにバージョンアップによって実装を取り替えることができます。
例えば、あるクラスでフィールドを公開した場合、派生したクラスでもそのフィールドは公開されます。
これは実装を公開しているため、派生先のクラスでも同じようにしか使うことができません。
しかし例えば、フィールドの代わりにプロパティを公開した場合、その実装を取り替えることができます。
例えばプロパティにセットしたデータをフィールドの代わりに別のオブジェクトやコレクションに保存したり、セットされるごとにイベントを励起したり、あるいは不正な値で例外を起こしたりできます。
これらの変更を行っても使用する側の変更は不要で、同じ手続きで扱うことができ、オブジェクトを部品化できます。
オブジェクト指向では、詳細を隠蔽してオブジェクト同士がメッセージを送りあうというのが肝なので、メッセージ送出にあたるメソッドやプロパティのみ公開されるわけです。
まとめ
この回答をまとめるとこうなります。
- ゲッター・セッターのみのプロパティを作るのはフィールドを公開しないため
- フィールドを公開しないのは公式情報でそのようなガイドラインが公開されている(つまりそのようなプログラミングを理想として C# が設計されている)ため
- そのガイドラインがあるのは、オブジェクト指向言語である(基本的な考えとして実装の隠蔽がある)ため
- 実装の隠蔽(カプセル化)の利点としては、主に次の二つ。不正なデータの設定を防ぐため、またインターフェースの更新をせず別の実装と交換できるようにするため(オブジェクトの部品化とポリモーフィズム)
以上です。
投稿2021/07/28 04:29
編集2021/07/28 05:06総合スコア28669
0
こんにちは。
回答は既に出揃っていると思うので、補足的に概念の説明をしてみます。
まず最初に表題に回答すると、単純な getter/setter は必要です。
プロパティとフィールドの最も大きな違いは、値の検証を記述できるかどうかなどではなく、「それがオブジェクト指向の文脈に乗るかどうか」です。
オブジェクトが備えるべき「性質」のうち、オブジェクトの状態を覗き見れるレンズの存在を表すものがプロパティです。
対して、フィールドはオブジェクト指向のレイヤには現れない「実装」の領域の概念です。
これらを隠すことで、オブジェクト指向のレイヤ上でのみプログラムを考えることができるようになるのです。
これが、フィールドを公開してはならないとガイドラインに定められている理由です。
単純な getter/setter とは、「状態を読むことができ、また自由に書き換えられる」という性質をオブジェクト指向の文脈上で規定したものであるため、単にフィールドを公開することとは意味が違います。
とはいえ、C# ではどちらでも同じような記述で同じように利用できてしまうため、カプセル化の観点からもプロパティの存在意義を示します。
例によって、getter/setter ともに自動実装のプロパティの存在意義について、以前の回答から文章を貼り付けておきます。
オブジェクトの変数を public にすると、他の誰もが値を自由に変更することが出来る。言い換えると、状態を変更する「責任」がその値を変更する側に分散する。getter/setter を介して private 変数を操作する設計にすると、状態を変更する「責任」は、そのオブジェクト自身が持つことになる。こうやって、オブジェクトの状態を管理する「責任」をそれぞれのオブジェクトに閉じ込めること、これが getter と setter の存在意義です。
投稿2021/07/28 08:37
総合スコア4252
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
「分からない」のケースでは、パブリックプロパティなど使わなくてもパブリックフィールドでいいんじゃないかと思っているのですよね。
以前別のスレッドで書いたことですが、再度まとめて以下に書いておきます。「分かる」の例も混じっています。
(1) オブジェクト指向の概念の一つ「カプセル化」を実現するため、通常クラス内の各フィールドへの直接アクセスは禁止するようにしておき、外部からはパブリックプロパティで各フィールドの値を取得したり設定したりするということがもともとのプロパティの目的。
(2) プロパティを使う目的には、開発者が意図した規則に基づいてフィールドを正しく使用できるよう保証するということもあります。例えば、以下の記事ように、ユーザーが Visual Studio でプロパティを設定する際、範囲外であると例外をスローするようなこともできます。
Web Custom Control の例外処置
http://surferonwww.info/BlogEngine/post/2010/08/06/Exception-handling-by-web-custom-control.aspx
(3) Entity Framework Code First でのモデルを定義を行う場合はフィールドではダメで、プロパティの定義が必要です。
新しいデータベースの Code First
https://docs.microsoft.com/ja-jp/ef/ef6/modeling/code-first/workflows/new-database
(4) ASP.NET Web Forms アプリのデータバインド式はプロパティでないとダメです。
(5) JSON にシリアライズするのもフィールドではダメでプロパティにする必要があります。(使うシリアライザにもよりますが、例えば System.Text.Json 名前空間の JsonSerializer ではプロパティでないとダメです)
投稿2021/07/28 04:47
退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
単純なgetter setter は必要なのか
OOPの文脈で、昔からよく出てくる話題ですね。
「ゲッター/セッターは、カプセル化のためにある」と言われます。
でも、小さなサンプルコードだけ見ると、「なぜ」そうするのか、イマイチ分かりにくい。
全体が100行くらいだったら、ゲッター/セッターがない方が、分かりやすく感じるでしょう。
そこで、プログラム全体で1万行以上、すでに書いてある、と想像してみてください。
そして、全体が大きくなると、「どこから呼ばれてるか、分からなくなってくる」のです。
100箇所以上から呼ばれると、どこでどう処理されて、とイチイチ覚えていられなくなります。
呼び出し元の処理がバラバラだとバグの元だから、一元的に処理する仕組みが必要だろうと。
そこで、処理とデータを一体化させて、データを保護するのが、カプセル化の考え方です。
プログラムが大きくなってくると、全体を見通せないので、
破綻しないよう整合性を管理する仕組みが必要になります。
このことを分かりやすく日常でたとえると、一戸建てで個室に鍵がなくても、
ホテルのフロントでは、全個室の鍵を管理する必要があるようなものです。
あるいは、大企業には入口に受付が用意されているようなものです。
マンションの一室にある零細企業だと、受付なんか要らないでしょう。
来る人はみんな顔見知りだろうし。でも、大企業だと来客は不特定多数です。
そういう言わば「組織化」の方法だから、組織が小さいうちは不要だと感じる。
実際、なくても回るし、ない方がスッキリする。でも、大きくなると必要だと。
さて、質問者の方の意図を汲み、ゲッター/セッターの必要性を説明しました。
……が! 一周回って、OO原理主義的な「ゲッター/セッター」不使用論
というのがあります。発展的話題として、こちらも紹介しておきます。
ゲッターで何かの変数を取ってきて → 値を処理して → セッターで戻す、
というのは、カプセル化としては中途半端ではないか、
結局中身を外部から変更可能ではないか、というわけです。
では、どうするか? 「求めるな、命じよ」というOOの格言のように、
なるべくクラスのデータ処理はクラスで完結させ、ゲッター/セッターを介せず、
クラスに付いているメソッドで処理するようにしよう、というわけです。
たとえば、自動車のオブジェクトには、外からゲッター/セッターを介して、
速度や座標を計算して与えるのではなくて、オブジェクト自身にさせようと。
外部に公開するメソッドは、アクセルやブレーキのような単純な操作にすると。
あるいは、経理課の人(クラス)から帳簿のデータを見せてもらって、
他の部署(営業とか)の人が計算したデータを返すのではなくて、
会計のことは経理課の人たちで完結させるようにしようと。
これは現実的には、テストでゲッター/セッターがある方が便利だとか、
貫徹するのが難しい部分もありますが、考え方としてはアリでしょう。
というか、じつは私自身は、むしろこちらに近い立場です。
さて、もしかしたら、後半は混ぜ返す印象があったかもしれません。
ただ、ひとくちにOOといっても、考え方に幅があるので、
広く紹介しました。読者の方で取捨選択してください。
投稿2021/07/28 11:41
総合スコア5592
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/28 13:49
2021/07/28 14:10 編集
2021/07/28 14:20
2021/07/28 14:27
2021/07/28 14:40
2021/07/28 14:47
2021/07/28 15:03
2021/07/28 15:52
2021/07/28 21:59 編集
2022/06/12 17:10
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
2021/07/28 13:01
2021/07/28 13:34 編集
2021/07/28 13:56 編集