Как бы вы получили доступ к свойствам объекта из метода объекта? [закрыто]


Каков "чистый" или "правильный" способ доступа к свойствам объекта из метода объекта, который не является методом получения/установки?

Я знаю, что снаружи объекта вы должны использовать геттер/сеттер, но изнутри вы бы просто сделали:

Java:

String property = this.property;

PHP:

$property = $this->property;

Или вы бы сделали:

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Простите меня, если моя Java немного не в порядке, прошел год с тех пор, как я программировал в Ява...

РЕДАКТИРОВАТЬ:

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

Author: D.C., 2008-08-01

18 answers

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

 59
Author: Greg Hurlman, 2008-08-01 16:32:17

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

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

 42
Author: MojoFilter, 2008-08-01 18:23:59

Я довольно удивлен тем, насколько единодушно мнение о том, что getters и сеттеры хороши и хороши. Я предлагаю зажигательную статью Аллена Голуба " Добытчики И Сеттеры - это Зло". Конечно, название предназначено для шоковой ценности, но автор делает обоснованные замечания.

По сути, если у вас есть getters и setters для каждого частного поля, вы делаете эти поля такими же хорошими, как и публичные. Вам было бы очень трудно изменить тип частного поля без волновых эффектов для каждого класса, который называет это getter.

Более того, с строго ОО точки зрения, объекты должны отвечать на сообщения (методы), которые соответствуют их (надеюсь) единой ответственности. Подавляющее большинство getters и setters не имеют смысла для составляющих их объектов; Pen.dispenseInkOnto(Surface) имеет для меня больше смысла, чем Pen.getColor().

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

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

 25
Author: moffdub, 2015-11-15 17:36:30

Это зависит от того, как используется свойство. Например, предположим, что у вас есть объект student, у которого есть свойство name. Вы можете использовать свой метод Get, чтобы извлечь имя из базы данных, если оно еще не было извлечено. Таким образом, вы сокращаете количество ненужных обращений к базе данных.

Теперь предположим, что у вас есть частный целочисленный счетчик в вашем объекте, который подсчитывает, сколько раз было вызвано имя. Возможно, вы захотите не использовать метод Get изнутри объекта, потому что это произведите неверный подсчет.

 19
Author: Shawn, 2008-08-01 16:19:04

Я что, просто перегибаю палку?

Возможно;)

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

PHP:

public function getName() {
    $this->incrementNameCalled();
    return $this->_getName();
}

protected function _getName() {
    return $this->name;
}

А затем изнутри самого объекта:

PHP:

$name = $this->_getName();

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

 13
Author: pix0r, 2008-08-01 16:43:30

PHP предлагает множество способов справиться с этим, включая магические методы __get и __set, но я предпочитаю явные методы получения и установки. Вот почему:

  1. Проверка может быть размещена в установщиках (и получателях, если на то пошло)
  2. Intellisense работает с явными методами
  3. Нет вопроса, доступно ли свойство только для чтения, только для записи или для чтения-записи
  4. Получение виртуальных свойств (т.Е. вычисленных значений) выглядит так же, как и обычные свойства
  5. Вы можете легко установить свойство объекта, которое на самом деле нигде не определено, которое затем становится недокументированным
 13
Author: Unlabeled Meat, 2011-11-27 22:17:18

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

Доводя это до конца, получатель должен вызвать получатель, который должен вызвать получатель.

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

 11
Author: Egg Vans, 2012-11-20 12:44:37

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

 7
Author: Allain Lalonde, 2008-08-22 11:15:45

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

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

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

 7
Author: Aadith, 2010-01-20 08:32:59

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

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

  doSomethingWithProperty() {
     doSomethingWith( this.property ) ;
  }

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

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

 7
Author: Martin Spamer, 2017-07-18 19:04:27

Что ж, похоже, что при реализации свойств C#3.0 по умолчанию решение принимается за вас; вы ДОЛЖНЫ установить свойство с помощью (возможно, частного) средства настройки свойств.

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

 6
Author: Coincoin, 2008-08-01 16:56:55

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

 6
Author: Brendon-Van-Heyzen, 2008-08-18 17:37:01

Частные поля с общедоступными или защищенными свойствами. Доступ к значениям должен проходить через свойства и копироваться в локальную переменную, если они будут использоваться в методе более одного раза. Если и ТОЛЬКО если у вас есть остальная часть вашего приложения, настолько полностью измененная, усовершенствованная и оптимизированная для того, чтобы доступ к значениям, проходя через их ассоциированные свойства, стал узким местом (и этого никогда не произойдет, я гарантирую), если вы даже начнете рассматривать возможность предоставления все, что не относится к свойствам, напрямую касается их вспомогательных переменных.

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

 6
Author: Mel, 2008-08-18 17:43:29

Если я не буду редактировать свойство, я буду использовать открытый метод get_property(), если только это не особый случай, такой как объект MySQLi внутри другого объекта, в этом случае я просто опубликую свойство и буду ссылаться на него как $obj->object_property.

Внутри объекта для меня всегда есть свойство $this->.

 6
Author: Ross, 2008-08-22 11:34:06

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

 6
Author: Steve McLeod, 2008-10-21 09:01:59

Я могу ошибаться, потому что я самоучка, но я НИКОГДА НЕ использую общедоступные свойства в своих классах Java, они всегда являются закрытыми или защищенными, так что доступ к внешнему коду должен осуществляться получателями/установщиками. Это лучше для целей технического обслуживания/модификации. И для внутреннего кода класса... Если метод получения тривиален, я использую свойство напрямую, но я всегда использую методы установки, потому что при желании я мог бы легко добавить код в события запуска.

 6
Author: Telcontar, 2018-02-15 11:07:09

Как указано в некоторых комментариях: иногда вы должны, иногда не должны. Самое замечательное в частных переменных заключается в том, что вы можете видеть все места, где они используются, когда вы что-то меняете. Если ваш геттер/сеттер делает что-то, что вам нужно, используйте это. Если это не имеет значения, решайте сами.

Можно было бы сделать противоположный случай: если вы используете геттер/сеттер, и кто-то меняет геттер/сеттер, они должны проанализировать все места, где геттер и сеттер используются внутри чтобы посмотреть, не испортит ли это что-нибудь.

 5
Author: svrist, 2008-08-01 17:01:27

Мне нравится ответ cmcculloh, но, похоже, наиболее правильным является ответ Грега Херлмана. Используйте геттеры/сеттеры постоянно, если вы начали использовать их с getgo и/или привыкли с ними работать.

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

 5
Author: Community, 2017-05-23 12:25:34