Strukturen haben auch in Java ihren Platz. Sie sollten sie nur verwenden, wenn die folgenden beiden Dinge zutreffen:
- Sie müssen nur Daten aggregieren, die kein Verhalten aufweisen, z. B. als Parameter übergeben
- Es spielt keine Rolle, welche Art von Werten die aggregierten Daten haben
Wenn dies der Fall ist, sollten Sie die Felder öffentlich machen und die Getter / Setter überspringen. Getter und Setter sind sowieso klobig, und Java ist albern, weil es keine Eigenschaften wie eine nützliche Sprache hat. Da Ihr strukturähnliches Objekt ohnehin keine Methoden haben sollte, sind öffentliche Felder am sinnvollsten.
Wenn jedoch eine dieser Bedingungen nicht zutrifft, haben Sie es mit einer echten Klasse zu tun. Das bedeutet, dass alle Felder privat sein sollten. (Wenn Sie unbedingt ein Feld mit einem besser zugänglichen Bereich benötigen, verwenden Sie einen Getter / Setter.)
Um zu überprüfen, ob sich Ihre mutmaßliche Struktur verhält, prüfen Sie, wann die Felder verwendet werden. Wenn es gegen Tell zu verstoßen scheint, fragen Sie nicht , dann müssen Sie dieses Verhalten in Ihre Klasse verschieben.
Wenn sich einige Ihrer Daten nicht ändern sollten, müssen Sie alle Felder endgültig ausfüllen. Sie könnten erwägen, Ihre Klasse unveränderlich zu machen . Wenn Sie Ihre Daten validieren müssen, geben Sie die Validierung in den Setters und Konstruktoren an. (Ein nützlicher Trick besteht darin, einen privaten Setter zu definieren und Ihr Feld in Ihrer Klasse nur mit diesem Setter zu ändern.)
Ihr Bottle-Beispiel würde höchstwahrscheinlich beide Tests nicht bestehen. Sie könnten (erfundenen) Code haben, der so aussieht:
public double calculateVolumeAsCylinder(Bottle bottle) {
return bottle.height * (bottle.diameter / 2.0) * Math.PI);
}
Stattdessen sollte es sein
double volume = bottle.calculateVolumeAsCylinder();
Wenn Sie die Höhe und den Durchmesser ändern würden, wäre es die gleiche Flasche? Wahrscheinlich nicht. Die sollten endgültig sein. Ist ein negativer Wert für den Durchmesser in Ordnung? Muss Ihre Flasche größer sein als breit? Kann das Cap null sein? Nein? Wie validieren Sie das? Angenommen, der Kunde ist entweder dumm oder böse. ( Es ist unmöglich, den Unterschied zu erkennen. ) Sie müssen diese Werte überprüfen.
So könnte Ihre neue Flaschenklasse aussehen:
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...
}