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

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

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

Джава:

String property = this.property;

PHP:

$property = $this->property;

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

Джава:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

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

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

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

1.08.2008 16:10:30
18 ОТВЕТОВ
РЕШЕНИЕ

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

61
1.08.2008 16:32:17
не делает ничего другого в установщике, кроме установки значения свойства в качестве примера неправильного использования в Java.
euphoria83 9.08.2010 02:37:19
@ euphoria83 Возможно, но это не мешает этому случиться.
Greg Hurlman 10.08.2010 03:19:02
Я согласен с оригинальным ответом. Однако помните, что если вы устанавливаете или получаете что-то личное внутри класса или объекта, вам нужно убедиться, что метод получения / установки не является циклическим или избыточным в некотором смысле, что приводит к сбою кода. Если вы не можете использовать getter / setter, тогда обращайтесь к нему напрямую. (Например, ваш метод получения / установки получает доступ к вторичному (частному / защищенному) методу для манипулирования данными.)
Rick Mac Gillis 10.02.2020 13:26:42

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

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

42
1.08.2008 18:23:59

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

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

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

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

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

25
15.11.2015 17:36:30

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

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

18
1.08.2008 16:19:04
Если объект Student является бизнес-объектом / объектом домена, теперь вы смешиваете детали инфраструктуры. В идеале бизнес / доменные объекты должны быть связаны только с бизнес / доменной логикой.
moffdub 19.09.2008 00:19:04
Что, если вы добавите в метод получения что-то вроде логического типа, например: PHP: public function getName ($ outsideCall = true) {if ($ outsideCall) {$ this-> incrementNameCalled (); } вернуть $ this-> name; } и затем внутри самого объекта, если вы вызываете get name, вы можете не допустить его увеличения на: PHP: $ name = $ this-> getName (false); Я просто иду за борт здесь?
cmcculloh 23.01.2010 18:37:45

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

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

Я просто иду за борт здесь?

Возможно;)

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

PHP:

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

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

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

PHP:

$name = $this->_getName();

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

12
1.08.2008 16:43:30

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

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

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

11
20.11.2012 12:44:37
Я руководствовался той же потребностью, которую вы должны были прокомментировать ... Плюс на это ответ не был закрыт;)
Egg Vans 25.07.2013 12:31:33

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

7
22.08.2008 11:15:45

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

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

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

7
20.01.2010 08:32:59

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

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

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

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

7
18.07.2017 19:04:27

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

6
18.08.2008 17:37:01

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

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

6
18.08.2008 17:43:29

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

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

6
22.08.2008 11:34:06

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

6
21.10.2008 09:01:59

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

6
15.02.2018 11:07:09

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

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

5
1.08.2008 16:56:55

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

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

5
23.05.2017 12:25:34

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

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

4
1.08.2008 17:01:27