Javaであっても、構造体には場所があります。次の2つのことが当てはまる場合にのみ使用してください。
- 振る舞いのないデータを集約する必要があります。例えば、パラメータとして渡すためです。
- 集約データがどのような値を持つかは少しも重要ではありません
この場合、フィールドをパブリックにし、ゲッター/セッターをスキップする必要があります。とにかくゲッターとセッターは不格好であり、Javaは有用な言語のようなプロパティを持たないことについて愚かです。いずれにせよ、構造体のようなオブジェクトにはメソッドが必要ないため、パブリックフィールドは最も意味があります。
ただし、これらのいずれかが当てはまらない場合は、実際のクラスを扱っています。つまり、すべてのフィールドはプライベートでなければなりません。(よりアクセスしやすい範囲のフィールドがどうしても必要な場合は、ゲッター/セッターを使用してください。)
想定される構造体に動作があるかどうかを確認するには、フィールドがいつ使用されるかを調べます。tellに違反していると思われる場合は、質問しないで、その動作をクラスに移動する必要があります。
一部のデータを変更しない場合は、それらのすべてのフィールドを最終的なものにする必要があります。クラスを不変にすることを検討してください。データを検証する必要がある場合は、セッターとコンストラクターで検証を提供します。(便利なトリックは、プライベートセッターを定義し、そのセッターのみを使用してクラス内のフィールドを変更することです。)
ボトルの例は、両方のテストに失敗する可能性が高くなります。次のような(工夫された)コードを使用できます。
public double calculateVolumeAsCylinder(Bottle bottle) {
return bottle.height * (bottle.diameter / 2.0) * Math.PI);
}
代わりに
double volume = bottle.calculateVolumeAsCylinder();
高さと直径を変更した場合、同じボトルになりますか?おそらくない。これらは最終的なものでなければなりません。直径の負の値は大丈夫ですか?ボトルは幅よりも高くなければなりませんか?キャップをヌルにすることはできますか?番号?これをどのように検証していますか?クライアントが愚かまたは悪であると仮定します。(違いを見分けることは不可能です。)これらの値を確認する必要があります。
これは、新しいBottleクラスの外観です。
public class Bottle {
private final int height, diameter;
private Cap capType;
public Bottle(final int height, final int diameter, final Cap capType) {
if (diameter < 1) throw new IllegalArgumentException("diameter must be positive");
if (height < diameter) throw new IllegalArgumentException("bottle must be taller than its diameter");
setCapType(capType);
this.height = height;
this.diameter = diameter;
}
public double getVolumeAsCylinder() {
return height * (diameter / 2.0) * Math.PI;
}
public void setCapType(final Cap capType) {
if (capType == null) throw new NullPointerException("capType cannot be null");
this.capType = capType;
}
// potentially more methods...
}