Являются ли открытые поля Java просто трагическим историческим недостатком дизайна на данный момент? [закрыто]

17

Похоже, что в этой точке ортодоксальность Java никогда не должна использовать открытые поля для состояния объекта. (Я не обязательно согласен, но это не относится к моему вопросу.) Учитывая это, было бы правильно сказать, что с того места, где мы находимся сегодня, ясно, что открытые поля Java были ошибкой / недостатком языкового дизайна? Или есть рациональный аргумент, что они являются полезной и важной частью языка, даже сегодня?

Благодарность!

Обновление: я знаю о более элегантных подходах, таких как C #, Python, Groovy и т. Д. Я не ищу эти примеры напрямую. Мне действительно просто интересно, есть ли еще кто-то в глубине бункера, бормочущий о том, как прекрасны общественные поля на самом деле, и как все массы - просто овцы и т. Д.

Обновление 2. Очевидно, что статические открытые открытые поля являются стандартным способом создания открытых констант. Я имел в виду больше использования открытых полей для состояния объекта (даже неизменяемого состояния). Я думаю, что это кажется недостатком дизайна, что нужно использовать открытые поля для констант, но не для состояния ... правила языка должны соблюдаться естественным образом, с помощью синтаксиса, а не руководящих принципов.

Ави Лен
источник
2
Каково ваше основание, что они действительно недостаток?
Аарон Макивер
1
Есть ли другой способ создания символических константных выражений в Java сейчас?
Эдвард Стрендж,
@ Аарон, я не утверждал, что это недостаток, я заявлял, что воспринял это как ортодоксальность в том смысле, что никогда не следует использовать публичные поля. Это восприятие может быть неправильным, но это действительно то, что я понял.
Ави Лен
@Crazy Eddie Я забыл об этом использовании, я думал о более распространенном использовании полей, состояние. Я отредактирую вопрос.
Ави Лен

Ответы:

14

Они мне нравятся до тех пор, пока поле является окончательным и используется только внутри приложения, а не раскрывается в API для других приложений. Это делает ваш код короче и более читабельным.

Вы не должны выставлять открытые поля в API, потому что, выставляя открытые поля, вы также открываете реализацию. Если getXXX()вместо этого вы представите его как метод, вы можете изменить реализацию, не меняя интерфейс API. Например, вы можете изменить и получить значение от удаленного сервиса, но приложения, использующие API, не должны это знать.

Это жизнеспособный дизайн для public finalполей в неизменяемых классах.

Из эффективной Java :

Пункт 14: В открытых классах используйте методы доступа, а не открытые поля

... если класс является закрытым для пакета или закрытым вложенным классом, нет ничего плохого в раскрытии его полей данных. Этот подход генерирует меньше беспорядка, чем подход метода доступа.

Хотя публичному классу никогда не рекомендуется открывать поля напрямую, это менее вредно, если поля являются неизменяемыми.

См. Также Почему я не должен использовать неизменяемые POJO вместо JavaBeans?

Jonas
источник
Просто интересно, каковы ваши причины не выставлять это в API?
Стивен Джеурис
2
@ Steven: Потому что, выставляя открытые поля, вы также выставляете реализацию. Если getXXX()вместо этого вы представите его как метод, вы можете изменить реализацию, не меняя интерфейс API. Например, вы можете изменить и получить значение от удаленного сервиса, но приложения, использующие API, не должны это знать.
Джонас
@Jonas: Вообще-то, это вообще не кандидаты в константы.
Стивен Джеурис
@Steven: я говорю не о константах, а о публичных финальных полях в неизменяемых классах. Например, посмотрите, почему я не должен использовать неизменяемые POJO вместо JavaBeans?
Джонас
@Jonas: Это хороший вариант использования! Возможно, полезно немного обновить свой ответ, чтобы уточнить.
Стивен Джеурис
9

Использование пар методов get / set - трагический исторический недостаток дизайна. Я не могу думать о другом языке, который реализует свойства как многословно и неэффективно.

Кевин Клайн
источник
1
Хотя это и верно, это несколько касательно вопроса, который (по сути) заключается в том, что, учитывая выбор между методами set / get и открытыми полями, есть ли какие-либо веские причины для предпочтения полей в некоторых ситуациях? То, что другие языки предлагают лучшее решение проблемы, мне кажется неуместным.
Жюль
5

Я думаю, что открытые поля подходят для класса, который по существу является типом значения, таким как комплексное число или точка, где класс делает немного больше, чем группирует примитивные типы вместе, как структура в стиле C, и, возможно, определяет несколько операторов.

Карл Билефельдт
источник
2
java.awt.Pointа друзья это немного кошмар.
Том Хотин - tackline
@ TomHawtin-tackline: Проблема Pointв том, что неоднозначно, должна ли переменная типа Pointинкапсулировать местоположения или инкапсулировать идентичность объекта с местоположением, которое может измениться. Концептуально, я бы посчитал код, который проходит вокруг, Pointочень похожим на код, который проходит вокруг массивов.
суперкат
Так что, если я получу Pointи изменим его, я должен ожидать, что объект, на который он ссылается, будет корректно обновляться на экране? Нет, проблема в Pointтом, что он изменчив. У нас было String/ StringBufferно идея, похоже, не прошла. / Передача массивов имеет похожие проблемы.
Том Хотин - tackline
5

Определить публичные константы все еще полезно. Например

public static final int DAYS_IN_WEEK = 7;

Тем не менее, по-прежнему предпочитайте enum где это возможно. Например

public enum Day {
    SUNDAY, MONDAY, TUESDAY, WEDNESDAY, 
    THURSDAY, FRIDAY, SATURDAY 
}

Для моделирования простых структурных классов это также полезно. Нет причин создавать геттер и сеттер для каждого поля, если они все равно являются публичными.

class Point
{
    public int x, y;
    public Point(int x, int y) {
        this.x = x;
        this.y = y;
    }
}
Стивен Джеурис
источник
Но опять же, многие утверждают, что структурам нет места в языке, подобном Java ...
1
@delnan: они почти такие же, как JavaBeans, но JavaBeans гораздо более многословен и не безопасен для потоков. См. Почему я не должен использовать неизменяемые POJO вместо JavaBeans?
Джонас
Некоторые специфичные для Android наблюдения: Перечисления оцениваются медленнее, чем целые, и их следует избегать. Кроме того, поля, к которым часто обращаются сеттеры и геттеры в узких циклах, также могут быть полезными из-за их общедоступности.
Nailer
2

До того, как IDE получили широкое распространение, обнародование всех ваших областей стало мощным инструментом для быстрого создания прототипов / проверок концепций.

В настоящее время существует очень мало оправданий для их использования, когда вы можете сгенерировать пару геттер / сеттер одним щелчком мыши.

biziclop
источник
4
Но 10 public finalполей более читабельно, чем 10 getXXX()методов.
Джонас
1
@Jonas Да, но мы не говорим о последних полях здесь. Если ваши открытые конечные поля также являются статическими, они являются константами, и достаточно constключевого слова, если они не являются статичными, это серьезное нарушение инкапсуляции.
Бизиклоп
3
@biziclop согласно Википедии : «хотя const зарезервировано как ключевое слово в Java, const не используется и не имеет функции»
Avi Flax
@Avi Flax Да, но его можно было использовать для маркировки констант, что исключало необходимость объявления констант в качестве открытых полей.
Бизиклоп
2
Предполагая, что пара геттер / сеттер вообще подходит, то есть. Это часто не так.
Дэвид Торнли
2

Это субъективно, но мое мнение таково, что все публичное / частное понятие устарело и задом наперед.

В питоне нет публичного / приватного; в основном все публично. Не вызвало много проблем.

В Java вы, как правило, создаете бессмысленные методы получения / установки для каждого поля, чтобы избежать греха пометить их как «публичные». (ИМХО, если вы обнаружите, что делаете это, просто отметьте их как общедоступные).

Hasen
источник
Python позволяет вам помечать вещи как частные, добавляя к имени префикс __. Это не на 100% приватно, так как есть еще способы доступа к этим переменным и методам, но тогда в C # вы можете делать подобные вещи с помощью отражения.
Адам Лир