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

StackOverflow https://stackoverflow.com/questions/126

  •  08-06-2019
  •  | 
  •  

Вопрос

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

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

Джава:

String property = this.property;

PHP:

$property = $this->property;

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

Джава:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

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

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

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

Это было полезно?

Решение

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

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

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

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

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

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

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

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

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

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

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

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

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

Я здесь просто переборщил?

Возможно ;)

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

PHP:

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

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

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

PHP:

$name = $this->_getName();

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

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

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

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

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

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

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

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

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

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

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

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

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

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

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

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

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

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

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

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

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

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

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

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

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

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top