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

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

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

Ява:

String property = this.property;

PHP:

$property = $this->property;

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

Ява:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

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

Обновлено:

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

Пользовательский скаляр GraphQL
Пользовательский скаляр GraphQL
Листовые узлы системы типов GraphQL называются скалярами. Достигнув скалярного типа, невозможно спуститься дальше по иерархии типов. Скалярный тип...
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
Как вычислять биты и понимать побитовые операторы в Java - объяснение с примерами
В компьютерном программировании биты играют важнейшую роль в представлении и манипулировании данными на двоичном уровне. Побитовые операции...
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Поднятие тревоги для долго выполняющихся методов в Spring Boot
Приходилось ли вам сталкиваться с требованиями, в которых вас могли попросить поднять тревогу или выдать ошибку, когда метод Java занимает больше...
Полный курс Java для разработчиков веб-сайтов и приложений
Полный курс Java для разработчиков веб-сайтов и приложений
Получите сертификат Java Web и Application Developer, используя наш курс.
97
0
17 790
18
Перейти к ответу Данный вопрос помечен как решенный

Ответы 18

Ответ принят как подходящий

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

ничего не делает в установщике, кроме установки значения свойства в качестве примера неправильного использования в Java.

euphoria83 09.08.2010 06:37

@ euphoria83 Возможно, но это не мешает этому случиться.

Greg Hurlman 10.08.2010 07:19

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

Rick Mac Gillis 10.02.2020 16:26

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

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

Если объект Student является бизнес-объектом / объектом домена, вы теперь смешиваете детали инфраструктуры. В идеале объекты бизнеса / домена должны быть связаны только с логикой бизнеса / домена.

moffdub 19.09.2008 04:19

Что, если вы добавите к получателю какое-то логическое значение, например: PHP: общедоступная функция getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } вернуть $ this-> name; } а затем из самого объекта, если вы вызвали get name, вы можете предотвратить его приращение с помощью: PHP: $ name = $ this-> getName (false); Я просто переборщил с этим?

cmcculloh 23.01.2010 21:37

Am I just going overboard here?

Возможно ;)

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

PHP:

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

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

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

PHP:

$name = $this->_getName();

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

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

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

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

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

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

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

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

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

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

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

Если вы имеете в виду «максимальную инкапсуляцию» под «пуристом», то я обычно объявляю все свои поля как частные, а затем использую «this.field» внутри самого класса. Для других классов, включая подклассы, я получаю доступ к состоянию экземпляра с помощью геттеров.

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

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

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

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

Я довольно удивлен, насколько единодушным является мнение о том, что getters и сеттеры хороши и хороши. Предлагаю зажигательную статью Аллена Голуба «Геттеры и сеттеры злы». Конечно, заголовок предназначен для шоковой оценки, но автор делает обоснованные выводы.

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

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

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

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

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

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

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

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

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

  1. Проверка может быть помещена в сеттеры (и геттеры, если на то пошло)
  2. Intellisense работает с явными методами
  3. Нет сомнений в том, доступно ли свойство только для чтения, только для записи или для чтения и записи.
  4. Получение виртуальных свойств (т. Е. Вычисленных значений) выглядит так же, как и обычные свойства.
  5. Вы можете легко установить свойство объекта, которое на самом деле нигде не определяется, а затем становится недокументированным.

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

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

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

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

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

Подводя итог этому, геттер должен вызвать геттер, который должен вызвать геттер.

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

Меня подтолкнуло то же, что и вам нужно было прокомментировать ... Плюс ответ не был закрыт;)

Egg Vans 25.07.2013 16:31

Другие вопросы по теме