Модификаторы доступа в объектно-ориентированном программировании - PullRequest
7 голосов
/ 11 марта 2010

Я не понимаю модификаторы доступа в ООП. Почему мы делаем, например, переменные экземпляра Java частными, а затем используем общедоступные методы getter и setter для доступа к ним? Я имею в виду, в чем причина / логика за этим?

Вы все еще получаете переменную экземпляра, но зачем использовать методы setter и getter, когда вы можете просто сделать ваши переменные общедоступными?

прошу прощения за мое невежество, потому что я просто пытаюсь понять, почему?

Спасибо заранее. ; -)

Ответы [ 9 ]

11 голосов
/ 11 марта 2010

Это называется data или скрытие информации .

По сути, вы не хотите, чтобы пользователь (читай: другой программист или вы) ковырялся во внутренних элементах вашего класса, потому что это очень затрудняет изменение вещей.

С другой стороны, четкое разделение между интерфейсом и реализацией (теоретически) позволяет легко что-то изменить внутри, не затрагивая пользователей вашего класса.

Например, предположим, у меня есть элемент управления Button с полем public String text. Теперь все начинают использовать мой Button, но я понимаю, что кнопка должна перекрашиваться на экране всякий раз, когда изменяется текст. Мне не повезло, потому что мой объект не может определить, когда назначен text. Если бы я сделал это private и предоставил вместо него setText(), я мог бы просто добавить вызов repaint для этого метода установки.

В качестве другого примера, предположим, у меня есть какой-то класс, который открывает файл в своем конструкторе и присваивает ему public FileStream file. Конструктор выдает исключение, если файл не может быть открыт. Поэтому другие методы в классе могут предполагать, что это поле всегда допустимо. Тем не менее, если кто-то будет копаться в моем классе и устанавливает file на null, все методы в моем классе внезапно начнут падать.

6 голосов
/ 11 марта 2010

Очень важный момент, который часто упускают из виду: у вас нет , чтобы обеспечить геттер и сеттер для каждого поля! Фактически, большинство полей не должны иметь ни одного, или только геттера (что делает их доступными только для чтения).

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

1 голос
/ 11 марта 2010

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

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

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

1 голос
/ 11 марта 2010

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

1 голос
/ 11 марта 2010

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

1 голос
/ 11 марта 2010

Разница в том, что с помощью методов получения и установки вы контролируете доступ к полям экземпляра. Вы можете предоставить защитные копии, неизменные представления или даже преобразования полей вашего экземпляра. У вас есть скрытые ваши реальные детали реализации от других. Это хорошо!

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

0 голосов
/ 12 марта 2010

Вы говорите об основах ООП. Эта тема достойна прочтения хорошей книги. Различные блоги и форумы (один из которых SO) не подходят для получения фундаментальных знаний.

Если вы действительно хотите получить глубокое понимание таких основ, что жизненно важно для хорошего разработчика, тогда читайте соответствующие книги. "Код завершен" или "Объектно-ориентированный анализ" стоит прочитать их.

0 голосов
/ 11 марта 2010

Это основное преимущество использования ООП, полиморфизма, наследования и инкапсуляции.

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

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

0 голосов
/ 11 марта 2010

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

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

В качестве простого примера скажем, что важно, чтобы переменная-член класса никогда не была равна нулю - скажем, это сломает ваш класс. Если вы сделаете поле общедоступным, любой другой код может установить для этой переменной значение null, вы ничего не сможете сделать.

Если вы сделаете его закрытым и предоставите вместо него метод установки, вы можете защитить член от установки на ноль, можете ли вы контролировать, выбрасываете ли вы отмеченное / непроверенное исключение или просто игнорируете попытку.

...