setter/getter は不要

Javaに多いと思うが、こんな例をたくさん見かける。

public class MyClass {
    private int myField;
    public int getMyField() {
        return this.myField;
    }
    public void setMyField(int value) {
        this.myField = value;
    }
}

出典はパッと示せないが、教科書みたいな本にも書いてあって、「内部フィールドはprivateにすべし」みたいなルールがあったりする。

しかし、これは単に次のように書けば良い。

public class MyClass {
    public int myField;
}

簡潔に書けることを簡潔に書いて何が悪いのか。こんな風に言うと、「フィールドへのアクセスを隠蔽しないなんて云々」という話が聞こえてきそうだ。しかしながら、内部に持っているフィールドを単に公開するだけなら、別にフィールドを直接公開すればいい。set/getなんて当たり前な一行メソッドを用意するのはコードを汚している。

ちょっと意味が違うものに、次のような書き方がある。

public class MyClass {
    private int position;
    public int getPosition() {
        return this.position;
    }
    public void moveTo(int value) {
        this.position = value;
    }
    public void moveBy(int offset) {
        this.position += offset;
    }
}

これは、命令列としてのプログラムは最初の例と大して変わらない。内部変数を単に取り出したり、値を書き換えているだけだ。しかし、これらのメソッドは意味があり、必要なものだ。

なぜ冒頭の例のsetter/getterは不要といい、最後の例では必要というのかは、考えてほしい。それがOOを理解しているかどうかのひとつの境界だと思う。ちなみに私は setXXX という名前のメソッドは大嫌いだ。

 

P.S.

ちなみに、Javaにはプロパティがないため、フィールドかメソッドかという実装の違いが契約(・規約・インターフェイス)に含まれてしまう。したがって、将来の仕様変更に対する防御策として盲目的にgetter/setterを作ることが必要悪として認められている節がある。これは言語設計の問題であって、getter/setterの存在意義の根拠にはならないと思う。さっさとC#のようなプロパティ構文を入れればいいのに。

P.P.S.

ちなみにC#でもフィールドを直接公開するよりプロパティにしろとされている。これは、フィールドアクセスもプロパティ呼び出しもソースコード構文は同一でも、CLIレベルではプロパティアクセス命令とメソッド呼び出し命令という違いが発生するため、種別を変えるとバイナリ互換性がなくなるからだ。ライブラリなど将来長期間使われるものにおいては問題になるため、予めプロパティにしておけ、ということだ(Javaの防御的なsetter/getterと問題構造は同じ)。

しかしながら、大半の開発者は「ソースコードもなく長期間使われる後方互換性が必要なライブラリ」というものはあまり関係ないため、実質的にフィールドにしようがプロパティにしようが関係ないことがほとんど。(なお、Microsoftのライブラリに公開フィールドが非常に少ないのはこの理由だと思う。)似たような事由で、const 定数を使うよりも static readonly フィールドにせよ、というガイドラインもある。