Item 16:In public classes,use accessor methods,not public fields(共通クラスでは、共通フィールドではなくアクセサメソッドを使用)

5597 ワード

Occasionally, you may be tempted to write degenerate classes that serve no purpose other than to group instance fields:
インスタンスフィールドをグループ化する以外に、他の用途のない劣化クラスを作成する場合があります.
// Degenerate classes like this should not be public!
class Point {
    public double x;
    public double y;
}

Because the data fields of such classes are accessed directly, these classes do not offer the benefits of encapsulation (Item 15). You can’t change the representation without changing the API, you can’t enforce invariants, and you can’t take auxiliary action when a field is accessed. Hard-line object-oriented programmers feel that such classes are anathema and should always be replaced by classes with private fields and public accessor methods (getters) and, for mutable classes, mutators (setters):
これらのクラスのデータフィールドは直接アクセスされるため、これらのクラスはパッケージ化のメリットを提供していません(Item-15).APIを変更しないと表現形式を変更することができず、不変量を実施することもできず、フィールドへのアクセス時に補助的な操作を行うこともできない.オブジェクト向けの思考を堅持するプログラマーは、このようなクラスが嫌われていると考え、プライベートフィールドとパブリックアクセスメソッドgetterを使用するクラスに取って代わられるべきであり、可変クラスについては、付与メソッドsetterである:
// Encapsulation of data by accessor methods and mutators
class Point {
    private double x;
    private double y;
    public Point(double x, double y) {
        this.x = x;
        this.y = y;
    }
    public double getX() { return x; }
    public double getY() { return y; }
    public void setX(double x) { this.x = x; }
    public void setY(double y) { this.y = y; }
}

Certainly, the hard-liners are correct when it comes to public classes: if a class is accessible outside its package, provide accessor methods to preserve the flexibility to change the class’s internal representation. If a public class exposes its data fields, all hope of changing its representation is lost because client code can be distributed far and wide.
もちろん、共通クラスに関連する場合、強硬派は正しいです.クラスがパッケージ外にアクセスできる場合、クラスの内部表現を変更する柔軟性を維持するためにアクセサメソッドが提供されます.共通クラスがデータフィールドを公開する場合、クライアントコードが広く配布されるため、その表現形式を変更するすべての希望は空になります.
However, if a class is package-private or is a private nested class, there is nothing inherently wrong with exposing its data fields—assuming they do an adequate job of describing the abstraction provided by the class. This approach generates less visual clutter than the accessor-method approach, both in the class definition and in the client code that uses it. While the client code is tied to the class’s internal representation, this code is confined to the package containing the class. If a change in representation becomes desirable, you can make the change without touching any code outside the package. In the case of a private nested class, the scope of the change is further restricted to the enclosing class.
ただし、クラスがパッケージレベルのプライベートまたはプライベートネストクラスである場合、データフィールドを公開しても本質的なエラーはありません(クラスが提供する抽象をうまく記述できると仮定します).クラス定義においても、使用するクライアントコードにおいても、この方法による視覚的混乱はアクセス方法よりも少ない.クライアントコードはクラスの内部表現にバインドされていますが、このコードはクラスを含むパッケージに限られています.表示形式を変更する場合は、接触しないでください.パッケージ外部の任意のコードの場合に変更します.プライベートネストされたクラスの場合、変更の範囲は閉じたクラスにさらに制限されます.
Several classes in the Java platform libraries violate the advice that public classes should not expose fields directly. Prominent examples include the Point and Dimension classes in the java.awt package. Rather than examples to be emulated, these classes should be regarded as cautionary tales.As described in Item 67, the decision to expose the internals of the Dimension class resulted in a serious performance problem that is still with us today.
Javaライブラリのいくつかのクラスは、共通クラスがフィールドを直接公開すべきではないという提案に違反しています.突出した例は、java.awtパケット中のPointおよびDimensionを含む.これらのクラスは真似されるべきではなく、警告と見なすべきである.Item-67に記載されているように、Dimensionクラスの内部構造の開示は、現在も深刻なパフォーマンスの問題を引き起こしている.
While it’s never a good idea for a public class to expose fields directly, it is less harmful if the fields are immutable. You can’t change the representation of such a class without changing its API, and you can’t take auxiliary actions when a field is read, but you can enforce invariants. For example, this class guarantees that each instance represents a valid time:
共通クラスの直接公開フィールドは決して良いアイデアではありませんが、フィールドが可変でなければ、危害は小さくなります.クラスのAPIを変更せずにクラスの表現形式を変更したり、フィールドを読み取るときに補助操作をしたりすることはできませんが、不変量を実施することができます.たとえば、このクラスは、各インスタンスが有効な時間を表すことを保証します.
// Public class with exposed immutable fields - questionable
public final class Time {
    private static final int HOURS_PER_DAY = 24;
    private static final int MINUTES_PER_HOUR = 60;
    public final int hour;
    public final int minute;

    public Time(int hour, int minute) {
        if (hour < 0 || hour >= HOURS_PER_DAY)
            throw new IllegalArgumentException("Hour: " + hour);
        if (minute < 0 || minute >= MINUTES_PER_HOUR)
            throw new IllegalArgumentException("Min: " + minute);
        this.hour = hour;
        this.minute = minute;
    } ... // Remainder omitted
}

In summary, public classes should never expose mutable fields. It is less harmful, though still questionable, for public classes to expose immutable fields.It is, however, sometimes desirable for package-private or private nested classes to expose fields, whether mutable or immutable.
要するに、共通クラスは可変フィールドを公開すべきではない.共通クラスでは、公開可変フィールドの危害は小さいが、潜在的な問題がある.しかしながら、パケットレベルのプライベートまたはプライベートネストクラスは、クラスが可変であっても可変であっても公開フィールドを必要とする場合がある.
Back to contents of the chapter(チャプターディレクトリに戻る)
  • Previous Item(前の項目):Item 15:Minimize the accessibility of classes and members(クラスとメンバーのアクセス性を最小限に抑える)
  • Next Item(次の項目):Item 17:Minimize mutability(可変性を減らす)