- PR -

getter/setter

投稿者投稿内容
架空兎
ベテラン
会議室デビュー日: 2003/08/18
投稿数: 78
お住まい・勤務地: さいたま氏
投稿日時: 2004-09-19 01:01
引用:

でゅうくさんの書き込み (2004-09-18 17:08) より:

アクセッサの意味をフィールドへ純粋に(加工や検査を行わず)アクセスするメソッドと定義するということは、public な getter と setter を必要とするようなフィールドに関しては、フィールドのスコープ自体を public にしてしまうの変わらない気がします。
スレッドの趣旨はクラス内部での扱いですが、そもそもアクセッサは外部へのインタフェースなので、その意味を固定してしまうということはそういうことです。
外部から見てそのクラスの内部構造は関心の外側にあるべきなので、フィールドへ純粋にアクセスする手段を提供するというアクセッサの定義には問題があると思います。


アクセサメソッドではフィールドへ純粋にアクセスしなければならないと
いうつもりはないですが、ただ、getter と setter の両方を持つプロパティは
setter で設定した内容とその直後に getter で取得される内容は
等しくあるべきという考えから、できるだけ加工は行わず、
そのままフィールドへアクセスするのが望ましいと思っています。
未記入
ぬし
会議室デビュー日: 2004/09/17
投稿数: 667
投稿日時: 2004-09-19 03:21
ちょっと便乗して別の質問。

外部からフィールドへの直接アクセスは、**例外なく必ず禁止して** setter/getter を介すようにしていますか? 私は、特定用途向けに作った汎用性の低いクラス(おおくの場合 package private なクラス)であれば、setter/getter を用意せず、フィールド自体を public で公開してしまうんですが…。
ちょま吉
大ベテラン
会議室デビュー日: 2004/08/04
投稿数: 112
投稿日時: 2004-09-19 03:52
私は、getterとsetterはその他のクラスとの間の依存性を弱くする為のものと認識しています。(他にも理由はあると思いますが、、、)
クラス間の依存性を弱く保ちたい理由は、、、ご存知ですよね。。。。
aa
ぬし
会議室デビュー日: 2004/01/08
投稿数: 299
投稿日時: 2004-09-19 08:53
引用:

外部からフィールドへの直接アクセスは、**例外なく必ず禁止して** setter/getter を介すようにしていますか? 私は、特定用途向けに作った汎用性の低いクラス(おおくの場合 package private なクラス)であれば、setter/getter を用意せず、フィールド自体を public で公開してしまうんですが…。


例外なく禁止すべきだと思います。
そのpackageの開発をあなた以外がすることもあるでしょう。
もしあなたしか絶対開発しないというのであっても、(内部的に)その変数の型を変えたくなったり、変数名を変えたくなったりする事もあるでしょうし、setするときに他の変数も併せて初期化するようにしたくなるかもしれません。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-09-20 14:00
unibon です。こんにちわ。

引用:

unibonさんの書き込み (2004-09-16 22:34) より:
getter/setter 経由が良さそうだと感じる場面では、おそらくクラスの集約構造がうまくいってなくて、クラスが複雑になりすぎていることが多いのではないかと考えます。たとえば、ひとつのクラスにフィールドが10個も20個もあって、メソッドも何十個も備えているような場合です(個数は程度問題ですが)。


この例としてはつぎのようなクラスを考えてみました。100個(固定)の要素を持つリスト構造とそのソート機能を持ったクラスです。内部で配列を持っているのですが、なにかの理由でその先頭の3要素を使いたくない、という変な制約を持ちます(例なので)。
コード:
public class SortableList {

    private int offset = 3;
    private int[] elements = new int[100 + offset];

    public int get(int index) {
        return elements[index + offset];
    }
    
    public void set(int index, int value) {
        elements[index + offset] = value;
    }

    public int size() {
        return elements.length - offset;
    }
    
    public void sortA() {
        int i;
        for (i = 0; i < size() - 1; i++) {
            int j;
            for (j = i + 1; j < size(); j++) {
                if (get(j) < get(i)) {
                    int t = get(j);
                    set(j, get(i));
                    set(i, t);
                }
            }
        }
    }

    public void sortB() {
        int i;
        for (i = 0; i < elements.length - offset - 1; i++) {
            int j;
            for (j = i + 1; j < elements.length - offset; j++) {
                if (elements[j + offset] < elements[i + offset]) {
                    int t = elements[j + offset];
                    elements[j + offset] = elements[i + offset];
                    elements[i + offset] = t;
                }
            }
        }
    }
    
    public static void main(String[] args) {
        SortableList list = new SortableList();
        for (int i = 0; i < list.size(); i++) {
            list.set(i, (int)(Math.random() * 100));
        }
        list.sortA();
        // list.sortB();
        for (int i = 0; i < list.size(); i++) {
            System.out.println("i = " + i + ", value = " + list.get(i));
        }
    }
}


ソート機能として、機能的には同じですが sortA と sortB の2つのメソッドを対比のために持っていますが、どう見ても getter/setter を使っている sortA のほうがキレイに見えます。それに比べると getter/setter を使わずにフィールドに直接アクセスしている sortB は非常に煩雑になっています。このような状況を考えると、一見、getter/setter メソッドを使ったほうが良いという考えにつながると思います。
しかし、このクラスは getter/setter を云々する以前に、クラス構造が悪いのです。本来は、リストを保持するクラスと、ソートのクラスは分けるべきなのです。たとえば Java 標準の java.util.ArrayList クラスと java.util.Collections クラスのように。
きよの
常連さん
会議室デビュー日: 2004/02/07
投稿数: 34
投稿日時: 2004-09-21 11:57
きよの と申します。

引用:

aaさんの書き込み (2004-09-19 08:53) より:
例外なく禁止すべきだと思います。
そのpackageの開発をあなた以外がすることもあるでしょう。
もしあなたしか絶対開発しないというのであっても、(内部的に)その変数の型を変えたくなったり、変数名を変えたくなったりする事もあるでしょうし、setするときに他の変数も併せて初期化するようにしたくなるかもしれません。



package private な場合は、アクセサは無くてもいいと思いますが。
変数の型や名前を変更したくなるときは、アクセサの型や名前も変えたくなりませんか?
その時点でアクセサがなく、ある変数へ値を設定するときに別の変数の値を設定したくなったら、その時にリファクタリングをすれば良いだけだと思うのですが。

# ちなみに私は、自己カプセル化フィールドもよく使います。
unibon
ぬし
会議室デビュー日: 2002/08/22
投稿数: 1532
お住まい・勤務地: 美人谷        良回答(20pt)
投稿日時: 2004-09-21 12:31
unibon です。こんにちわ。

自己カプセル化(Self-Encapsulation)という言葉は、私はあまり良く知らなかったのですが、自己カプセル化用のメソッドが public であることまでも規定している技法なのでしょうか。自己カプセル化の実現だけならば private であっても良いような気がします。ちなみに、
http://www.refactoring.com/catalog/selfEncapsulateField.html
を見たのですが、アクセス修飾が省かれていました。おそらく、自己利用(Self-Use)とは並列に存在する概念だと考えます。
永井和彦
ぬし
会議室デビュー日: 2002/07/03
投稿数: 276
お住まい・勤務地: 東京都
投稿日時: 2004-09-21 15:09
引用:

202837さんの書き込み (2004-09-19 03:21) より:
ちょっと便乗して別の質問。

外部からフィールドへの直接アクセスは、**例外なく必ず禁止して** setter/getter を介すようにしていますか? 私は、特定用途向けに作った汎用性の低いクラス(おおくの場合 package private なクラス)であれば、setter/getter を用意せず、フィールド自体を public で公開してしまうんですが…。



私の場合は、フィールドは全て例外無くprivateにして、アクセサのスコープを適宜設定する方向で統一しています。

アクセサを一々定義することの不利益と言えば
・コード量(手間)が増える
・関数呼び出しのオーバーヘッド
……の主に2点かと思うのですが、前者に関しては最近の開発環境は(ある程度)吸収してくれますし、後者に関しては誤差範囲ではないかと思います。

逆にアクセサ利用の利益としては、アクセサ経由だとsetterとgetterのスコープを自在に調整出来るのが嬉しいです。まあ、再三再四言われているように、変更にも(ある程度)強くなりますし。Trapを追加しやすいのも魅力ですね。

で、とりあえず「不利益がほぼ無く、利益はある(場合もある)」ということで、例外無く作成するという行動パターンになっています。
主張として「アクセサを作らなければならない」という仰々しいものでは無く、単純に「アクセサを作るのを躊躇う理由が無い」というものですね。

で、「方針はシンプル、しかも一律」なので、後からコードを追いやすいです。
「基本的にはこうだけど、package privateなクラスの場合はこうなって、さらに別のケースでは……」と基本ルールが複雑なのは大変なのではないかなーとも思います。

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