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

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

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

Java:

String property = this.property;

PHP:

$property = $this->property;

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

Java:

String property = this.getProperty();

PHP:

$property = $this->getProperty();

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

EDIT:

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

18 ответов


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


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

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


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

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

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

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

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


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

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


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

возможно ;)

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

PHP:

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

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

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

PHP:

$name = $this->_getName();

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


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

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

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

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

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


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


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

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

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


путь пуриста ОО избежать обоих и следовать закон Деметры С помощью скажи Не спрашивай подход.

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

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

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

  doSomethingWithProperty( this.daysPerWeek() ) ;

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


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

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


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


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

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


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

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


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


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


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

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


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

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