Почему атрибуты в Java могут быть открытыми? - PullRequest
43 голосов
/ 09 декабря 2011

Как всем известно, Java следует парадигмам ориентации объекта, где инкапсуляция данных говорит о том, что поля (атрибуты) объекта должны быть скрыты для внешнего мира и доступны только через методы или что методы являются * только интерфейс класса для внешнего мира. Так почему же можно объявить поле в Java как публичное, что противоречит парадигме инкапсуляции данных?

Ответы [ 12 ]

74 голосов
/ 09 декабря 2011

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

Например, я часто выставляю открытые статические члены конечных данных как открытые (например, константы).Я не думаю, что это вредно.

Я укажу, что эта ситуация верна и для других языков, кроме Java: C ++, C # и т. Д.

Языки не всегда должны защищать нас от нас самих,

В примере с Оли, какой вред, если я напишу это так?

public class Point {
   public final int x;
   public final int y;

   public Point(int p, int q) {
      this.x = p;
      this.y = q;
   } 
}

Он неизменен и поточно-ориентирован.Члены данных могут быть общедоступными, но вы не можете причинить им вред.

Кроме того, это маленький грязный секрет, что «частное» в действительности не является частным в Java.Вы всегда можете использовать отражение, чтобы обойти это.

Так что расслабьтесь.Все не так плохо.

52 голосов
/ 09 декабря 2011

Для гибкости. Было бы очень больно, если бы я не смог написать:

class Point {
    public int x;
    public int y;
}

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

12 голосов
/ 09 декабря 2011

Потому что жесткая «инкапсуляция данных» - не единственная парадигма и не обязательная особенность ориентации объекта.

И, более конкретно, если у кого-то есть атрибут данных, который имеет открытый метод установки и открытый метод получения, и методы не делают ничего, кроме фактической установки / получения атрибута, какой смысл сохранять его закрытым?

5 голосов
/ 09 декабря 2011

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

2 голосов
/ 09 декабря 2011

Обсуждение хорошей стороны публичных переменных ... Понравилось ...:)

Может быть много причин для использования public переменных. Давайте проверим их по одному:

Performance

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

Константы

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

public static final String ACCEPTABLE_PUBLIC = "Acceptable public variable";

Другие случаи

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

1 голос
/ 09 декабря 2011

Java является ответвлением от языков синтаксиса стиля C. Те языки поддерживали struct s, которые были фиксированными псевдонимами смещения для блока памяти, который обычно определялся как «один элемент». Другими словами, структуры данных были реализованы с struct s.

Хотя использование структуры напрямую нарушает цели инкапсуляции объектно-ориентированного программирования, когда Java был впервые выпущен, большинство людей были гораздо более компетентны в итеративном (процедурном) программировании. Предоставляя члены как public, вы можете эффективно использовать класс Java точно так же, как вы могли бы использовать C struct, даже если базовые реализации этих двух сред были радикально различными.

Есть несколько сценариев, где вы можете даже сделать это с правильной инкапсуляцией. Например, многие структуры данных состоят из узлов двух или более указателей, один из которых указывает на «содержащиеся» данные, а один или более указывает на «другие» соединения с остальной частью структуры данных. В таком случае вы можете создать закрытый класс, который не имеет видимости вне класса «структура данных» (например, внутренний класс), и поскольку весь ваш код для обхода структуры содержится в одном и том же файле .java, вы может удалить методы .getNext() внутреннего класса для оптимизации производительности.

1 голос
/ 09 декабря 2011

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

Лучше всего всегда инкапсулировать в Java по одной простой причине. Если вы не инкапсулируете, вы не сможете позже инкапсулировать без изменения подписи объекта. Например, если у вашего сотрудника есть имя, и вы делаете его публичным, это имя employee.name. Если позже вы захотите инкапсулировать его, вы получите employee.getName () и employee.setName (). это, конечно, сломает любой код, использующий ваш класс Employee. Таким образом, в Java рекомендуется инкапсулировать все, чтобы вам никогда не приходилось изменять сигнатуру объекта.

Некоторые другие языки OO (ActionScript3, C # и т. Д.) Поддерживают истинные свойства, когда добавление метода получения / установки не влияет на сигнатуру. В этом случае, если у вас есть метод получения или установки, он заменяет открытое свойство той же сигнатурой, чтобы вы могли легко переключаться назад и вперед, не нарушая код. В этих языках практика всегда заключать в капсулу больше не нужна.

0 голосов
/ 24 января 2015

Я действительно не могу придумать вескую причину не использовать геттеры и сеттеры вне лени. Эффективная Java, которая считается одной из лучших книг по Java, когда-либо говорила, всегда использует геттеры и сеттеры. Если вам не нужно слышать о том, почему вы всегда должны использовать геттеры и сеттеры, пропустите этот абзац. Я не согласен с примером ответа Point на «Point» как время, чтобы не использовать геттеры и сеттеры. Есть несколько проблем с этим. Что делать, если вам нужно изменить тип номера. Например, однажды, когда я экспериментировал с графикой, я обнаружил, что часто меняю свое мнение относительно погоды: я хочу сохранить местоположение в java Shape или непосредственно как int, как он продемонстрировал. Если бы я не использовал геттеры и сеттеры и изменил это, мне пришлось бы изменить весь код, который использовал местоположение. Однако, если бы я не сделал этого, я мог бы просто заменить геттер и сеттер.

Методы получения и установки - это боль в Java. В Scala вы можете создавать открытые члены данных, а затем получать и / или устанавливать без изменения API. Это дает вам лучшее из обоих миров! Возможно, Java исправит это однажды.

0 голосов
/ 15 ноября 2013

Использование public или нет на самом деле зависит от того, существует ли инвариант для обслуживания. Например, чистый объект данных никоим образом не ограничивает переход состояния, поэтому не имеет смысла инкапсулировать элементы с помощью набора методов доступа, которые не предлагают больше функциональности, которая представляет элемент данных как открытый.

Если у вас есть как средство получения, так и средство установки для конкретного не частного элемента данных, который предоставляет не более функциональные возможности, чем получение и настройка, тогда вы можете переоценить свой дизайн или сделать его общедоступным.

0 голосов
/ 14 декабря 2011

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

...