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