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

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

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

Java:

String property = this.property;

PHP:

$property = $this->property;

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

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

Простите меня, если моя Java немного выключена, это был год с тех пор, как я запрограммировал Java...

EDIT:

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

Ответ 1

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

Ответ 2

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

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

Ответ 3

Я довольно удивлен, насколько единодушны в том, что getters и сеттеры - это хорошо и хорошо. Я предлагаю зажигательную статью Аллена Голуба " Getters And Setters Evil". Конечно, название имеет значение шока, но автор делает правильные баллы.

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

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

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

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

Ответ 4

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

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

Ответ 5

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

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

Ответ 6

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

Возможно;)

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

PHP:

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

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

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

PHP:

$name = $this->_getName();

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

Ответ 7

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

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

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

Ответ 8

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

Ответ 9

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

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

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

Ответ 10

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

Ответ 11

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

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

Ответ 12

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

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

Ответ 13

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

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

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

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

Ответ 14

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

Ответ 15

Ну, похоже, что реализация свойств С# 3.0 по умолчанию выполнена, решение принято за вас; вам нужно установить свойство, используя (возможно, частный) набор свойств.

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

Ответ 16

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

Ответ 17

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

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

Ответ 18

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

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