- PR -

getter/setter

投稿者投稿内容
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-09-16 22:34
unibon です。こんにちわ。

引用:

hirayさんの書き込み (2004-09-16 14:56) より:
ところで、それを知って以降、コーディングのたびに疑問に思うことがあるのですが、
*******************************************************************************
フィールドの参照/更新を、他クラスからではなく、自クラス内で行う場合にも、
やはりgetter/setterを使った方がいいんでしょうか?
それとも、自クラスのフィールドの場合は、
直接、フィールドの参照/更新をしてしまっていいんですか?
*******************************************************************************


私は、フィールドを直接に参照・更新したほうが良い、という主義です。
なお、上記の「自クラス」という意味は、this だけなのか、それとも
コード:
public class Hoge {

    private int x;
    private Hoge hoge;
    
    public int getThisX() {
        return this.x;
    }

    public int getHogeX() {
        return hoge.x;
    }
}


における hoge も含むのかどうかの2通りの解釈があるかなと思います。
#「自クラス」を文字通り受け取れば、this も hoge も両方なのでしょうけど。

私は、this に対してはフィールドに直接アクセスしたほうが良いとは思います。
一方、hoge に対してはしないほうが良いかなと思いますが、こっちはちょっと迷うところです(話しを簡単にするため、これはちょっとこの投稿では省きます)。

なぜ、(this に対して)フィールドに直接アクセスのほうが良いかと言えば、クラス構造をプリミティブにすると、自ずとフィールド直接アクセスになるはずだと思うからです。getter/setter 経由が良さそうだと感じる場面では、おそらくクラスの集約構造がうまくいってなくて、クラスが複雑になりすぎていることが多いのではないかと考えます。たとえば、ひとつのクラスにフィールドが10個も20個もあって、メソッドも何十個も備えているような場合です(個数は程度問題ですが)。こういうのは、本来はそのクラスが別の小さなクラスを集約するようにして、フィールドの個数を減らすべきです。そうなると、getter/setter でアクセスするのが逆に煩わしくなります。煩わしくなると言っても、本来は getter/setter でアクセスするのが良いけど端折ってフィールドに直接アクセスしたくなる、という意味ではなく、フィールドに直接アクセスするほうが自然に感じる、という意味です。
ぬべたそ
ベテラン
会議室デビュー日: 2003/12/18
投稿数: 72
投稿日時: 2004-09-16 22:48
こんばんは。興味深く拝見させて頂いています。
私もクラス内のプロパティへのアクセスは、setter/getterを通さない直接アクセスに一票です。
引数付のコンストラクタ内で、
--------------------------------
public void Foo(int x){
setX(x);
}
--------------------------------
とかあまり見かけたことがありません。

一つご質問させて頂きたいのですが、「自己カプセル化」というのはどのように実現できるのでしょうか?
普通、privateなプロパティに関しては、他のクラスからはsetter/getterを通さなければアクセス出来ませんので、これを「カプセル化」と呼ぶのだと思いますが、「自己カプセル化」とは??自クラス内のプロパティを変更できなくするのであれば、「final」を使うのかなと思いますが、これだとsetter/getterを通しても変更できません。

******以下追記
「自己カプセル化」で検索したら結構ヒットしました。
Martin FowlerのHPには
I don't use it all the time, but I do use it from time to time.
っていう記述があります。


[ メッセージ編集済み 編集者: taiping 編集日時 2004-09-16 22:56 ]
okutin
ベテラン
会議室デビュー日: 2003/12/11
投稿数: 98
お住まい・勤務地: 広島
投稿日時: 2004-09-17 09:43
こんにちは。

私はメソッドを使う派ですね。
世の中完璧なモノは無いし何が起こるかも分からないので、事前にできることがあるのならやっておくほうが吉ではないかなという考えです。
hiray
会議室デビュー日: 2004/03/02
投稿数: 2
投稿日時: 2004-09-17 10:17
こんにちは。投稿者のhirayです。

ぱっと見る限り、getter/setter利用派と、直接派は、半々ぐらいな感じですね。
定石としてこうする、というのがないみたいで、ちょっと意外です。
それと、会社(など)のコーディング規約にこうしなさいとあるから、
というご意見がなかったのも、かなり意外です。(ただ出てこなかっただけかな?)

ちなみに、言い出しっぺの私は、getter/setterを使った方がいいのかな、と思うようになりました。
というのもやはり、先々なにかあった時(チェックロジックの追加、クラス分割など)に、
対応がしやすそうな感じがします。
がるがるさんの、「昨日の自分は赤の他人」というお言葉は、なるほど納得です。

とはいえやはり、「カプセル化」の視点から考えると、
自クラスでのgetter/setterは意味がなさそうなのも確かだと思います。
質問の際「カプセル化」について触れたのがちょっと余計でしたね。


いろいろなご意見ありがとうございました。とても参考になりました。

Yoshitake
会議室デビュー日: 2004/07/07
投稿数: 6
投稿日時: 2004-09-17 10:29
私は クラス内部でも極力getter/setter使用に賛成です。
以前、こんなのがありました。(コードはJavaです)

class メンバー
{
  private String 名前_;

  public String get名前()
  {
    return 名前_;
  }

  public String toString()
  {
    return get名前();
  }
}

メンバークラスのtoStringで名前を表示していたのですが、
データ項目に変更が入って、

class メンバー
{
  private String 姓_;
  private String 名_;

  public String get名前()
  {
    return 姓_ + 名_; // ←「NullPointerに気をつけろ」という突っ込みはなしでお願いします。
  }

  public String toString()
  {
    return get名前();
  }
}

となりました。が、toStringメソッドはgetterを使用していたため変更なしでOKでした。

ってことで、
通常はgetter/setterを使用、特殊な事情のときはフィールド直接でやっています。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-09-17 14:27
unibon です。こんにちわ。

引用:

Yoshitakeさんの書き込み (2004-09-17 10:29) より:
class メンバー
{
  private String 姓_;
  private String 名_;

  public String get名前()
  {
    return 姓_ + 名_; // ←「NullPointerに気をつけろ」という突っ込みはなしでお願いします。
  }

  public String toString()
  {
    return get名前();
  }
}

となりました。が、toStringメソッドはgetterを使用していたため変更なしでOKでした。


この例だと、「get名前」メソッドの役割が変わってしまっているとも言えます。もともとは「get名前」メソッドはひとつのフィールドを返す役割だったのに、複数のフィールドから導出する役割に変わっています。私は、そのような変更にまで対処するためのカプセル化はやりすぎでは、と考えます。
開発プロジェクトの最中において、コードは移ろいやすいものですから、たしかに変更に強い設計も一理あります。しかし、これはやりすぎだと思います。
#「やりすぎ」という言葉もなんだか変な言い回しですが、ちょっとほかに思いつきませんでした。

なお、「get名前」メソッドのアクセス修飾が、private ならば、すなわち、
コード:
private String get名前()


ならば、このメソッドの役割は、文字列連結のサブルーチンなので、他の public なメソッドから呼ばれるのも別段構わないと思います。
okutin
ベテラン
会議室デビュー日: 2003/12/11
投稿数: 98
お住まい・勤務地: 広島
投稿日時: 2004-09-17 14:46
こんにちは。

引用:

unibonさんの書き込み (2004-09-17 14:27) より:

この例だと、「get名前」メソッドの役割が変わってしまっているとも言えます。もともとは「get名前」メソッドはひとつのフィールドを返す役割だったのに、複数のフィールドから導出する役割に変わっています。私は、そのような変更にまで対処するためのカプセル化はやりすぎでは、と考えます。



privateの部分、つまり実装がどうなっていようと「get名前」メソッドが「名前」を返す役割であることは変わりないので問題ないと思うのですが。
極端な話、はじめから実際に「Hoge」というprivate変数は無くても「getHoge」や「setHoge」はあってもいいと思います。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-09-17 14:47
unibon です。追加です。

手もとの書籍を見てみましたが、もし getter/setter を使うと、たとえば、
Effective Java
http://www.amazon.co.jp/exec/obidos/ASIN/4894714361/
の「項目 14 継承よりコンポジションを選ぶ」の中で出てくる、「自己利用(self-use)」の問題とも関わってくると思います。特に setter が問題となるはずです。

#なお、getter/setter というのがひとつのフィールドと一対一に対応しているようなもの(座標のフィールド x,y に対応するメソッド getX(), getY() など)は、ここでは意味がないので考えていません。

スキルアップ/キャリアアップ(JOB@IT)