У каждого публичного свойства должны быть методы доступа? - PullRequest
2 голосов
/ 11 августа 2010

Я вхожу в ООП и сталкиваюсь со следующей дилеммой. У меня есть класс:

class Recipe {

    var $title;
    var $time;
    var $ingredients = array();
    var $instructions;
    var $category;

    function __construct($title, $time, $ingredients, $instructions, $category) {

        $this->title = $title;
        ...
    }

    function getTitle() {
        return $this->title;
    }

}

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

...
$recipe = new Recipe($title, $time, $ingredients, $instructions, $category);
echo $recipe->title; // versus $recipe->getTitle();

Похоже, я сэкономлю много времени, не определяя методы доступа. Однако мне интересно, каковы плюсы и минусы такого подхода?

Ответы [ 5 ]

4 голосов
/ 11 августа 2010

Методы получения / установки не одобряются в большинстве языков сценариев.Они были изначально представлены с Java и Java Beans специально.Сильная инкапсуляция имеет смысл в статически скомпилированном коде.В скриптовых языках любой доступ через интерпретатор в любом случае идет, а не напрямую к адресам памяти;отсюда и магические методы.В PHP вы можете маршрутизировать все через __get, что делает обертки избыточными.

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

4 голосов
/ 11 августа 2010

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

<?php
class Recipe {

    public $title;

    function __construct($title){
        $this->title = $title;
    }

    function getTitle(){
        return $this->title;
    }

}

$a = new Recipe('potatoes');
$t1 = microtime(true);
for($i=0;$i<1000000;$i++){
    $x = $a->title;
}
$t2 = microtime(true) - $t1;
echo $t2.'s<br/>';

$a = new Recipe('potatoes');
$t1 = microtime(true);
for($i=0;$i<1000000;$i++){
    $x = $a->getTitle();
}
$t2 = microtime(true) - $t1;
echo $t2.'s<br/>';

?> 

Эхо:

0.25662112236023s

1.0309250354767s

в 4 раза медленнее с геттером!

4 голосов
/ 11 августа 2010

Золотое правило ООП - всегда делайте вашу собственность приватной !Есть очень мало случаев, когда общедоступные свойства будут разрешены, но даже тогда, возможно, есть альтернативное решение.

Причина в том, что если вы сделаете ваши свойства общедоступными, любой может изменить их на все, что захочет.Большинство свойств не может быть просто любым значением.Ваше свойство $ title должно быть целым числом?Я очень сомневаюсь в этом.Так что, если вы или кто-то еще случайно установите его в целое число?Вы не обнаружите это.Он установит значение, и ваша программа будет продолжаться до тех пор, пока не произойдет сбой, потому что где-то ожидалась строка.Кроме того, скорее всего, ваши свойства должны быть проверены каким-либо образом, прежде чем они будут установлены.Вы бы включили всю эту проверку в установщик свойства.

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

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

Иногда вы думаете: «Хорошо, только я буду редактировать свой код, поэтому ничего не произойдет».Однако вы должны практиковать это сейчас.Получить в привычку делать это.Позже вы избежите неприятностей.

3 голосов
/ 11 августа 2010

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

Если вы используете магические функции PHP, вы можете написать динамический метод получения / установки для доступа к закрытым / защищенным свойствам.

<?php


/**
 * Implements auto get/set
 * class Entity extends GetterSetter {}
 * $name = $entity->getName(); // return $this->name;
 * $name = $entity->getFullName(); // return $this->full_name;
 * $entity->setFullName("Ian"); // $this->full_name = "Ian";
 */

class GetterSetter {
    public function __call($name, $args) {
        if (substr($name, 0, 3) == "get") {
            $key = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', (substr($name, 3, strlen($name)-3))));
            if (property_exists($this, $key)) {
                //print "/* GET " . $this . "->" . $key . " = " . $this->$key . "\n */";
                return $this->$key;
            }
        } elseif (substr($name, 0, 3) == "set") {
            $key = strtolower(preg_replace('/([a-z])([A-Z])/', '$1_$2', (substr($name, 3, strlen($name)-3))));
            if (property_exists($this, $key)) {
                //print "/* SET " . $this . "->" . $key . " = " . $args[0] . "\n */";
                return ($this->$key = $args[0]);
            } else {
                print "Key not found: " . $this . "->" . $key;
            }
        }
    }

}
?>
2 голосов
/ 11 августа 2010

С геттерами / сеттерами:

  • Вы можете изменить реализацию. Например, позже вы можете изменить getTime для подсчета количества $ инструкций вместо использования члена $ time.
  • Сеттеры могут выдавать исключения, проверять ввод или новое состояние, изменять другие данные, протоколировать ...

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...