Структуры имеют свое место, даже в Java. Вы должны использовать их, только если выполняются следующие две вещи:
- Вам просто нужно объединить данные, которые не имеют никакого поведения, например, передать в качестве параметра
- Неважно, какие значения имеют эти агрегированные данные
Если это так, то вы должны сделать поля общедоступными и пропустить методы получения / установки. Геттеры и сеттеры в любом случае неуклюжи, а Java глупа из-за отсутствия свойств, подобных полезному языку. Так как ваш структурный объект не должен иметь никаких методов, открытые поля имеют больше смысла.
Однако, если один из них не подходит, вы имеете дело с реальным классом. Это означает, что все поля должны быть приватными. (Если вам абсолютно необходимо поле в более доступной области, используйте метод получения / установки.)
Чтобы проверить, имеет ли ваша предполагаемая структура поведение, посмотрите, когда используются поля. Если это кажется нарушением, скажи, не спрашивай , тогда тебе нужно перенести это поведение в свой класс.
Если некоторые из ваших данных не должны измениться, вам нужно сделать все эти поля окончательными. Вы можете сделать свой класс неизменным . Если вам нужно проверить ваши данные, тогда предоставьте проверку в установщиках и конструкторах. (Полезный трюк состоит в том, чтобы определить частный установщик и изменить поле в вашем классе, используя только этот установщик.)
Ваш пример с бутылкой, скорее всего, провалит оба теста. Вы могли бы иметь (надуманный) код, который выглядит так:
public double calculateVolumeAsCylinder(Bottle bottle) {
return bottle.height * (bottle.diameter / 2.0) * Math.PI);
}
Вместо этого должно быть
double volume = bottle.calculateVolumeAsCylinder();
Если бы вы изменили высоту и диаметр, это была бы та же самая бутылка? Возможно нет. Это должно быть окончательным. В порядке ли отрицательное значение для диаметра? Должна ли ваша бутылка быть выше, чем она широкая? Может ли Cap быть нулевым? Нет? Как вы это проверяете? Предположим, клиент либо глуп, либо злой. ( Невозможно определить разницу. ) Вам необходимо проверить эти значения.
Вот как может выглядеть ваш новый класс 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...
}