Javaで実装するときに、以下のようにフィールドをprivateにしてsetterとgetterを実装するということがあるかと思います。
lang
1public class Product { 2 private String name; 3 private Integer price; 4 public String getName() { 5 return name; 6 } 7 public void setName(String name) { 8 this.name = name; 9 } 10 public Integer getPrice() { 11 return price; 12 } 13 public void setPrice(Integer price) { 14 this.price = price; 15 } 16}
最初にこれを見たときは、わざわざフィールドをprivateにしてsetterとgetterを実装する意味が分からず、以下のようにフィールドをpublicで実装してしまった方がコードも短くなって読みやすいのではないかと思いました。
lang
1public class Product { 2 public String name; 3 public Integer price; 4}
その後も、Javaでsetterとgetterを実装する理由について、周りのエンジニアの方々に質問したり、ググったりしてみたのですが、「Javaの仕様だから」、「オブジェクト指向だから」というような回答が多く、なかなか納得できる答えに出会えませんでした。
今では、私自身もなんとなくsetterとgetterを実装する習慣が付いてしまっているのですが、それでもsetterとgetterを実装する実質的なメリットはよく分かっていません。
この辺りの話題に詳しい方がいらっしゃったら、setterとgetterの意義について教えて頂けるとありがたいです。
よろしくお願い致します。
気になる質問をクリップする
クリップした質問は、後からいつでもMYページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

回答13件
0
発想としては、「外部に公開する仕様を、内部の実装とは関係なく決め打ちにできてしまう」ということがあります。
たとえば、メンバ変数として特定のルールに従った値を要求する場合、パブリックでそのまま代入するとその値を使う時点でしかチェックできませんが、setterを使えばその段階でチェックが可能となります。
また、変数という形では時々刻々と変わる値をその都度取得する、というような処理は実現することはできませんが、getterとすれば特に問題がありませんし、内部的に「処理して取得するもの」と「変数として持っているもの」とを区別することなく、外部から使えるようになります。
なお、C#やRubyなど、外から見れば変数代入に見えるけど、内部的にはアクセサを動作させるというような形で、明示的にアクセサを呼びださなくて済むようにした言語もあります。
投稿2015/03/30 02:01
総合スコア146544
0
このクラスに限って,あるいは,このような単純な情報の出し入れだけだったらおっしゃるようにgetter/setterを設けるメリットはないのかもしれません.
しかし,もっと多くの情報を扱うクラスで,他のクラスから勝手に操作されたくない情報というのはほぼ確実に出てきます.
例えば,Exceptionクラスには「原因」となるThrowableオブジェクトを格納するフィールドがあります.この仕組み上,1回原因を設定したあとは変更を加えられるのは望ましい状態であるとは言えません.このため,initCause(Throwable)
というメソッドがあります.setで始まりませんが,実質setterです.
すでにこのメソッドで原因を入れていたり,Exceptionのコンストラクタで原因を入れていたりした場合は例外を発生させる仕組みになっています.
そして,このようなgetter/setter"だけ"を設けた場合,どのフィールドに対してgetter/setterを付けたか,付けなかったかをいちいち考えてプログラムしなければならず,非常に使いづらいクラスになるでしょう.それなら全てにgetter/setterを設けて,アクセス方法を統一したほうがわかりやすいですし,ミスも減ると思います.
投稿2015/03/30 03:24
総合スコア20675
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
私も深く理解している訳ではないのですが、JavaBeansに即してではないかと思います。
以下の用途でJavaClassを使用する場合、getter/setterは必須になります。
・JSPのページからJavaClassをアクセスする
・JSFのBackingBean実装
・JavaEEにてDBアクセス用にModel(EntitiyBean)を作成する
フレームワークやライブラリを利用する際、スクリプトの記載からsetter名/getter名に変換
してインターフェースとする用法が多いようです。
投稿2015/03/30 03:09
総合スコア1339
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
getterとsetterがあることによって、例えば、下記のようにpriceに0以下の値をセットすることを禁止したりもできます。
もし、フィールドがpublicだったらこのような拡張ができませんね。
Java
1public class Product { 2 private String name; 3 private Integer price; 4 public String getName() { 5 return name; 6 } 7 public void setName(String name) { 8 this.name = name; 9 } 10 public Integer getPrice() { 11 return price; 12 } 13 public void setPrice(Integer price) { 14 if (price.intValue() >= 0) 15 // priceが0以上の場合はそのまま代入 16 this.price = price; 17 } else { 18 // 0以下の場合は例外をスローする 19 throw new HogeException("price is NOT positive number."); 20 } 21 } 22} 23```
投稿2016/03/13 14:52
編集2016/03/13 14:55総合スコア907
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
以前も同じような質問があったので、一応載せておきます。
投稿2015/03/31 07:44
総合スコア1679
0
はっきり言ってしまえば、getter/setterを書く方法と、当該フィールドをpublicにする方法とは、一長一短があり、議論の対象です。Kent Beckの「Smalltalkベストプラクティスパターン」などでも、両方の流儀の良さを述べていたと記憶します。
しかし、ことJavaに限っていれば、getter/setterを書く方法が主流であり、ほぼ議論の余地はありません。これは単純にJava Bean仕様によってそのように決めたので、特別な事情のないかぎり、その仕様に従っておく、ということが慣例になっているということです。
投稿2015/03/30 07:43
総合スコア973
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
確かにオブジェクト指向だからと言われるとわからないですよね。
基本的には以下のようなメリットがあるからでしょうか。
・オブジェクトの呼び出し元はオブジェクトの状態を意識せずに扱える。
→getterやsetterを定義するルールにしておけば、統一がしやすいってこともありますね
・オブジェクト内でしか使わない情報を隠せる。
→そのフィールドを他の処理でも使う場合などに直接アクセスされると困る場合など
・呼び出し元を意識せずに変更がしやすい。
→呼び出し元が知っているのはgetterとsetterだけなので、実際のgetterとsetterの処理が変更しやすい
・継承などを行ってもアクセスの方法が変わらない。
→継承先のsetterやgetterの処理を変えることもできる。
また、基本的にはオブジェクト間はメッセージをやりとりするような感覚で扱うので、
例えば、Aという人を表すオブジェクトに対して、「Aさん、名前!」というより「Aさん、名前を教えて!」という方が自然に扱えるからというのも考え方の一つとしてあっても良いかもしれません。
投稿2015/03/30 06:01
総合スコア254
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
他の言語から Java を見た場合の意見です。
Java は getter/setter(メソッド呼び出し)とフィールドアクセスの記法を揃えられません。
そのことから書き方を揃えるために getter/setter に寄せるのが一般的になっているのではないかと思います。
メソッド(getter/setter)とフィールドアクセスの違いは、アクセス時に処理をいれこめるかどうかの違いです。
単に値を運ぶだけならフィールドアクセスで良いのですが、必要時に計算して得る値となるとメソッドで実装するしかありません。
メソッドとフィールドアクセスには明確な構文の違いがあります。
value = a.getField();
a.setField(value);
value = a.field;
a.field = value;
この2つを混在させたくないから getter/setter に寄せるのではないかと思います。
1つに統一したいのはなぜかというと、
・単純に全体の統一感を維持したいから。
・もしも処理が必要になったときに、メソッドに変更するしかなく、その場合は全てのアクセス箇所を書き換える必要が出てくる。
というのが主な理由だと思います。
これが他の言語になると話は変わってきます。
getter/setter 定義用の専用の構文が用意されていて、
getter/setter とフィールドアクセスの書き方が統一されていて切り替え可能になっていたりします。
スクリプト言語である Ruby や C# なんかでも使えます。Java の派生言語である Scala なんかでも使えたような気がします。
そうした場合は段階的に最初はフィールドを直接アクセスさせておいて、必要になったら getter/setter に書き換えるということがしやすいです。
Java はそれがしずらいので、そろえるなら getter/setter にそろえるというのが一般的になっているように思います。
投稿2015/03/30 04:00
総合スコア297
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
クラスのプロパティに対するsetterメソッド(ミューテータ)、getterメソッド(アクセサ)の存在理由としては、そのクラスのプロパティを別のクラスから利用できるのがgetterだけ、つまり内容を取得するのを許可し、setterは許可しない、のように利用制限するために用います。
ただ単純にデータベースの検索結果や画面からの入力項目を格納する目的のクラス(DataTransferObjectと呼称されているものです)ならば、常にgetter/setterを両方使いますので、これらのメソッドは不要で、public化しても特に大きな問題にならないでしょう。
投稿2016/03/15 06:15
総合スコア12011
0
ベストアンサー
Javaに限ってのお話ですが、他の方が答えられているように、大半は、JavaBeansの仕様に従っているだけだと思います。
他のオブジェクトから操作されたくないような場合は、getterはまだしも、setterに関しては、この記事にあるように、単純に薄っぺらいラッパーではなく、別のかたちのメソッドになるように思えます。
また、インスタンスフィールドを公開しない理由としては、疎結合にするというのもあります。
疎結合にすることで、JMockitなどで、クラスをMock化する際に、accessorメソッドがあった方が、Mock化しやすいという利点もありますが、現実には、インスタンスフィールドを直接書き換えるなんて、リフレクションを使わない限りは、初心者くらい(バグ出しそうで、怖くて、普通はやらない)だと思うので、コンストラクターで初期化して、書き換えないような場合はpublic final、リフレクションで初期化してから使われるような場合は、publicにして公開してしまったりしています。
Javaの定石では、accessor(setter/getter)を用意するのですが、不要であれば直接公開もあり と言ったところでしょうか?
投稿2015/03/30 15:36
編集2015/03/31 04:04総合スコア30
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

0
カプセル化。
基本的にインスタンス変数は公開してはいけません。
どこでどうかえられたか管理できず煩雑になるため。
Beanのようなクラスではメリットはあまり見受けられないと思いますが、
Interfaceなどスコープを小さくする場合にメリットがあると思います。
投稿2015/03/30 15:05
総合スコア17
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
0
例えばDBと連携する自前のクラスを作るとします。そのクラス内にDBのオブジェクトをprivateな変数として持っておけば、そのクラス内からしか操作されない事が保証されますよね?
そうする事でprivateの意味が出てくるんじゃないかな?
カプセル化とか隠ぺいとかよく言われてるけど、プログラマー同士のメッセージ的な意味だと自分では思っています。
投稿2015/03/30 13:29

退会済みユーザー
総合スコア0
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。

退会済みユーザー
2015/03/30 13:38

0
私もあまり詳しいわけではありませんが、
オブジェクト指向のカプセル化という考え方に関係あると認識しています。
全てpublicのメンバ変数だと、外部で何か修正が加わった際にクラスの仕様をよくわかってない人が
入れてはいけない場所に入れてはいけない値を入れてしまうリスクが発生してしまいます
数値を期待している変数なのに文字列を突っ込んでしまうとか…
まずはAという変数に値を入れて、処理結果がBに入るのに、いきなりBに代入してしまうとか…
期待していない変数にいきなり文字列を突っ込まれて
「あれ?エラー…。ここで文字列を数値に変換してやる必要があるんじゃね?あれ、今度はこっちでエラー…じゃぁここをこうして…」
などと、クラスの仕様を理解してない人がコードを引っ掻き回して、せっかくきっちり作っていたのにソースコードがボロボロになってしまうかもしれません。
そういった場合もprivateでとっておけば、セッターがなければ代入できませんし、
セッターを通していれば、セットする段階で型などを判定してやればよいです
また、そういうコードをアクセサに仕込んであれば、あとでこのクラスを使おうと思った人が見たとき、
「あ、このアクセサには数値が入ることを期待しているんだな」とかわかりやすいと思います
多人数で大きなシステムを開発する上で非常に重要なのではないかなと思います
投稿2015/03/30 06:37
総合スコア23
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。
あなたの回答
tips
太字
斜体
打ち消し線
見出し
引用テキストの挿入
コードの挿入
リンクの挿入
リストの挿入
番号リストの挿入
表の挿入
水平線の挿入
プレビュー
質問の解決につながる回答をしましょう。 サンプルコードなど、より具体的な説明があると質問者の理解の助けになります。 また、読む側のことを考えた、分かりやすい文章を心がけましょう。
バッドをするには、ログインかつ
こちらの条件を満たす必要があります。