質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.48%
C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

Q&A

解決済

9回答

16362閲覧

getter, setterの必要性

hogeshi_

総合スコア47

C#

C#はマルチパラダイムプログラミング言語の1つで、命令形・宣言型・関数型・ジェネリック型・コンポーネント指向・オブジェクティブ指向のプログラミング開発すべてに対応しています。

8グッド

5クリップ

投稿2016/03/18 04:34

こんにちは
現在C#を勉強しているのですが、個人的にgetter, setterの必要性が無いように感じました
わざわざprivateなフィールドに外側からアクセスするためなら、getter,setterなど書かず、publicにしてしまえばいいのではないでしょうか。目的がわかりません。コードが長くなるだけではないのでしょうか。privateにする意味は外側から、アクセスされないためなのに結局アクセスする際の名前が変わっただけでアクセスできてしまう...これは意味がないんじゃ..とかんじました。

Moyashi159, tkanda, kazutarosu, Chironian, iwamoto_takaaki, argius, maisumakun, kuwako👍を押しています

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

argius

2016/03/18 05:45

プログラミングに関係がない質問ではないと思います。
guest

回答9

0

ちょっと調べ切れてないところがあるため、間違っているところがあるかも知れません。最初のオブジェクト指向であるSimulaについてはよくわからなかったので、割愛しています。なぜ、同じ事ができるpublicなフィールドなどと言う物があるのか?という疑問に対する読み物として読んでいただければと思います。なぜ、getterやsetterの方が良いのかは他の回答者さんの回答をお読みください。なお、この回答は純粋オブジェクト指向原理主義者の偏見に満ちています


getterとsetterの代わりにフィールドをpublicにすればいいという考えは間違っています。そもそも、フィールドにpublicを設定できるという言語仕様そのものが間違っています。publicなフィールドがある言語は間違った実装をいつまでも採用している欠陥言語なのです。

この間違いはC++に由来します。C++はCの仕様をそのまま拡張してオブジェクト指向を実現しようとしました。正当なオブジェクト指向であるSmalltalkのようなクラスを実装することもできました。それを実現したのがObjective-Cですが、話がずれるのでそれはまた機会があれば話しましょう。では、C++の開発者はどうしたかというと構造体を拡張してクラスを作るというとんでもない手法を生み出しました。

Cの構造体は単純です。ただのデータの羅列でしかありません。そこに、メンバーとして関数を足せば、オブジェクト指向っぽい何かになることに気付きました。あとは、適当にコンストラクタとか継承とかアクセス権とか定義すれば、オブジェクト指向っぽくコーディングできるようになりました。しかし、所詮毛の生えた構造体です。メンバー変数もメンバー関数も区別することができません。なので、メンバー変数をpublicにできるのは当たり前のことでした。

C++のオブジェクト指向は成功を収めました。構造体を拡張するという発想は内部構造が単純になるため、実装も簡単でした。その流れはPythonでも採用されましたし、C++からオブジェクト指向を抜き出したJavaがその路線を踏襲することも自明のことでした。Javaはオブジェクト指向の代名詞になるぐらいに流行し、C++の間違った実装こそがオブジェクト指向だと人々は思うようになりました。

そして、C#です。C#の先祖であるObject Pascal(Delphi)もまさしくその路線でした。また、Javaへの対抗意識を燃やしていたC#がJavaと同じような構造にすることで、Java開発者を引き寄せようという戦略としても、それは当たり前のことでした。こうしてC#にも構造体を拡張したなんちゃってオブジェクト指向が実装されてしまいました。

C++ではフィールドではなくメンバー変数であり、クラスは構造体の一種であるため、publicであることは気にすることはありませんでした。黒魔術師であるC++erにとって構造体であることこそが真実であり、オブジェクト指向の機能はおまけにすぎなかったからです。この間違いにいち早く気付いたのはJavaの開発者でした。彼らはpublicなフィールドを使わずに、privateにしてgetterとsetterを実装することを推奨しました。彼らはフィールドという存在をひた隠しにするべく躍起になりましたが、自ら課した互換性という縛りのために、開発者に永遠にgetterとsetterを書き続けることを強いりました。

そんな中、ある発明がありました。まるでフィールドのようにアクセスできるメソッドにすれば違和感もなくなるということです。C#のプロパティはまさしくそれでした。あたかもフィールドのようにアクセスできるgetterとsetterを実装できました。その中身がメソッドなのかフィールドなのかは見えないようにしたのです。さらに、自動的にgetterとsetterが設定されるような構文も追加しました。JavaにはできなかったことをC#はやってのけたのです。

しかし、publicなフィールドは残されました。負の遺産は消えていなかったのです。しかし、安心してください。C#は常に進化しています。そのような負の遺産も、コード分析をすればそいつを使うのはいけないよってちゃんと指摘してくれるようになっているのです。
CA1051: 参照できるインスタンス フィールドを宣言しないでください
さすがC#です。C#さえ使っていればオブジェクト指向は完璧です。単純なgetterとsetterも簡単に実装できます。Cに毛が生えたC++や、なんちゃってオブジェクト指向のJavaとは違います。C#さえ使っていれば問題ありません。Visual StudioやMSDNが勧めてくれる推奨を疑うことはMicrosoftに対する反逆です。Windowsユーザである資格がありません。C#さえ使っていれば幸せになれるのです。


オブジェクト指向するなら、純粋オブジェクト指向であるRubyがお勧めって回答にしようとしたんだけど、C#を勧める回答になってしまった。どうしてこうなった?

投稿2016/03/18 11:42

raccy

総合スコア21735

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

tkanda

2016/03/18 15:45

大変興味深く拝読いたしました。勉強になりました。
Chironian

2016/03/19 01:07

> フィールドにpublicを設定できるという言語仕様そのものが間違っています。 ふっふっふ。きっと予想されていると思いますが、ダウトです。 フィールドを全てprivateにしようという考え方そのものが間違っています。 もちろん、できるだけprivateにした方が良いです。でも、privateしか選択できないのは間違いです。 クラスが担う機能の抽象化を行い、できるだけ変更に強いクラス設計を行った結果、多くのフィールドは公開しないで済むようになります。しかし、データ構造の隠蔽が現実的ではなくそのままの形で外部からアクセスできるようにしたいフィールドが少し残ります。 それをprivateにしてgetterのみ実装しRead Onlyにするのか、publicで単純化するのか、選択できるべきです。 アクセサを経由すると、デバッグする人は中で変なことしてないかいちいち確認する必要があります。必要なら仕方がないですが、必要もないのに手間をかけさせるのは如何なものかと。 > 黒魔術師であるC++erにとって構造体であることこそが真実であり、オブジェクト指向の機能はおまけにすぎなかったからです。 あっはっは。同意します。 C++は、手続き型プログラミング、STL、メタ・プログラミングなどなどもできるマルチパラダイムで超高速な言語です。
raccy

2016/03/19 02:46

> > フィールドにpublicを設定できるという言語仕様そのものが間違っています。 > > ふっふっふ。きっと予想されていると思いますが、ダウトです。 > フィールドを全てprivateにしようという考え方そのものが間違っています。 他言語でのフィールドに相当する(?)インスタンス変数が、例え同じクラスであっても、インスタンス自身以外はアクセスできないRubyの設計こそが間違っていたんやーーー よし、今日から俺はC#erになる。
drumath2237

2016/03/22 09:50

・・・コワッ  オブジェクト指向信者ってこうなるケースもあるんですね・・・。lisp信者かと思いましたよ・・・。 確かにC#のオブジェクト指向は盤石でちゃんとしたフレームワークとかあってオブジェクト指向を学ぶのであれば申し分ないものですよね・・・C++も悪くない気がするのですが。  Cの構文はC#と違ってバージョンアップとかあまりないんですよね。それはCの開発者が最初からきちんと設計していたかららしくて、それを知ったMSの開発者がwindowsのネイティブコードにC/C++を採用したとか。さすがにデニスはC++ができるとは思わなかったと思いますが。  言語も個性なので一つの観点だけで判断しようとするのはよくないと思います。
guest

0

ベストアンサー

色々メリットがありますが、
メリットの1つとして.** 値の正当性チェックを入れることができる。**などがあります。
下記のサンプルはこちらから転載しています。

C

1public class Date 2{ 3 private int month = 7; // Backing store 4 5 public int Month 6 { 7 get 8 { 9 return month; 10 } 11 set 12 { 13 // 正当性チェック:1~12以外の値は代入しない。 14 if ((value > 0) && (value < 13)) 15 { 16 month = value; 17 } 18 } 19 } 20}

投稿2016/03/18 05:14

Odacchi

総合スコア907

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

0

私がよく書くやり方ですが

C#

1public int Count { 2 get; 3 private set; 4}

これだけでも十分メリットがあると思いますよ。

投稿2016/03/19 10:58

Yamamotize

総合スコア25

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

フィールドを private にして、単純な値の設定・取得のアクセサを public にするのがカプセル化だよ。
というのは違います。間違っています。

カプセル化という観点で見るならば、おっしゃる通りです。全然意味ないです。
オブジェクトが持つ実データを書き換えれて、実データを取得できるので、
フィールドを public にするのと違いはありません。

それ以外の観点から見た時、意味がないのか?というと、そこは人それぞれじゃないでしょうか。
僕は、set や get とタイプした時に、補完でズラっと出てきて欲しいので、
アクセサは用意しますね。

影響範囲を調査するときも、setterの呼び出し階層をたどれば、setしている場所が分かりますし。
ブレークポイントも貼れますし何かと便利ですよ。
publicフィールドにすると、set と get 両方が該当してしまい、目視による確認になりますので。

ただ、前述しましたがカプセル化という観点からだと無意味です。
そこは、そう理解したうえで書くべきだと思います。

ところで、C#にはアクセサメソッドって文化はあんまりなくないです?
プロパティとして書きますよね?

public string foo { set; get; } みたいな。

投稿2016/03/18 04:49

編集2016/03/18 05:18
root_jp

総合スコア4666

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

プロパティのいいところは、インターフェースに抜き出せるところなんですよね。
以下はどちらもその応用です。
http://qiita.com/yuba/items/baceffbdbcfdc03f7945
http://qiita.com/yuba/items/dd0b4f43ae311683363e

投稿2016/03/18 06:33

yuba

総合スコア5568

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

C#でgetter/setterというのがあまりしっくりこないのですが。プロパティのことでしょうか。

私も基本はプロパティにしますが、内部実装的なところではpublicフィールドにすることもあります。

積極的に使う理由としては、デバッグのしやすさというのがありますね。get/setのところでデバッグ出力などをして実行状況をトレースしたり、ブレークポイントを置いてロジックを確認したりということができます。

投稿2016/03/18 10:00

catsforepaw

総合スコア5938

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

既に先人の方たちが多くの議論をしています。リンク先にまとめがのっていますので、どうぞ。

投稿2016/03/18 04:40

Odacchi

総合スコア907

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

Chironian

2016/03/18 05:01

C#はsetter/getter=プロバティなので、リンク先の大半は該当しないと思います。
Odacchi

2016/03/18 05:06

いえ、getter/setterメソッドをget/setプロパティと読み替えて問題ありません。 本質は同じなので、逆に当てはまらないものは 『6. データがどこで参照/変更されているかがコード中で見やすい。』 くらいしかありませんよ。
Odacchi

2016/03/18 05:14

コメント欄だとソースコードの挿入ができないようなので、再度C#でのサンプルを別途投稿しました。
Chironian

2016/03/18 06:00

あっと、すいません。「大半」は言い過ぎました。 リンク先のメリットとして上げれられている先頭の3つは、変更した時に呼び出し側を修正する必要がないことですね。 C#はフィールドを使っていた場合でも、必要に応じてプロパティへ変更することで、呼び出し側のコードを変えること無く、クラス内部の実装を変更できます。 JavaやC++はそうはできません。最初からsetter/getterにしておく必要があります。 5~8は当たり前のことなのでついスルーしちゃいました。ごめんなさい。 ところで、「9. オブジェクト指向とはそういうものである。」は間違いです。 内部のフィールドをアクセスするだけのsetter/getterは内部構造を直接さわるのと事実上同じです。内部構造ではなく機能でI/Fするのがオブジェクト指向です。
Odacchi

2016/03/18 06:39

「普通のgetter/setterメソッドとget/setプロパティの最大の違いは?」 という議題であれば、Chironian さんが仰ることが最も大きな差かもしれません! 普段Javaばっかり触っているので、改めて、なるほどと思いました。ご指摘ありがとうございます。 また、9は、実は読んでいませんw
guest

0

か、か、「考えなしに使えること自体ラピッド開発ツール(RAD)の重要な目的の1つだから」じゃないかな。
http://d.hatena.ne.jp/Kityo/20150625/1435181833

投稿2016/03/25 22:51

savilerow

総合スコア12

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

0

たとえば以下の例だと、Kingaku の setter に 0 が渡された場合、KingakuStr は "0" になります。
Kingaku の setter が一度も呼ばれない場合は、空文字 "" です。

C#

1private int _kingaku = 0; 2private string _kingakuStr = ""; 3 4// 金額 (数値) 5public string Kingaku { 6 get { 7 return this._kingaku; 8 } 9 set { 10 this._kingaku = value; 11 this._kingakuStr = value.ToString(); 12 } 13} 14 15// 金額 (文字列) 16public string KingakuStr { 17 get { 18 return this._kingakuStr; 19 } 20}

他にも

「"1" をセットされても "01" をセットされても0埋めして "01" としてセットする」 とか、
「null の場合は "***" を返す」 とか、

プロパティ (getter/setter) にしておくと、こういうのを
呼出側のことは気にしないで
内部で勝手に書き換えられる点などが便利ですね。

一旦ただの public 変数で書いてしまうと、後から変更するのは大変ですし。
プロパティ (getter/setter) にしておけば如何様にもできます。

投稿2016/03/18 05:18

編集2016/03/18 05:20
sk_3122

総合スコア1126

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

ozwk

2016/03/18 06:03

> 一旦ただの public 変数で書いてしまうと、後から変更するのは大変ですし。 呼び出し側からの見た目が変わらないので、 publicフィールドからプロパティに変更するのは大変じゃないとおもいます。
sk_3122

2016/03/18 06:12 編集

ああそうか、プロパティだと見た目変わらないですね。 public string Hoge { get; set; } ... info.Hoge = ""; みたいにアクセスするし。 Java だと (プロパティじゃなくてまさにgetter/setterなので) info.getHoge(), info.setHoge("xxx") みたいな感じでちょっと変わるので・・・ ちょっとごっちゃになってました。すみません。
sk_3122

2016/03/18 10:02 編集

public 変数だと、 外部から誰かに setter が呼ばれているか、呼ばれていないか分からないけど、 getter しか public にしなければ 「値のセットは内部でしか行われていない。外部に公開されているのは getter のみ」 みたいな場合にわかりやすい、とかもメリットですかね。 (プロパティの場合は ReadOnly Property ですかね)
guest

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.48%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問