2011-12-31 2 views
4

Что считается лучшей практикой для написания классов ООП, когда речь идет об использовании свойства внутри страны.использовать класс getters или свойства класса? (PHP)

Рассмотрите следующий класс;

<?php 
Class Foo 
{ 
    /** 
    * @var null|string 
    */ 
    protected $_foo; 

    /** 
    * @return null|string 
    */ 
    public function getFoo() 
    { 
     return $this->_foo; 
    } 

    protected function _doSomething() 
    { 
     $foo = $this->_foo; 
     $result = null; 
     // ... 
     return $result; 
    } 
} 

Как вы видите, IM, используя _foo свойства в _doSomething(), хотя суб-класс может переопределить getFoo(), возвращающую вычисленное значение не сохраняется обратно в _foo; это недостаток.

Что мне делать?

  1. знак добытчик в качестве окончательного, используйте свойство внутренне (без дополнительных вызовов функций, не соблюдение конечного разработчика использовать _foo как свойство, так как он защищен)
  2. использование getFoo() внутренне, знак _foo как частное (дополнительная функция звонки)

Оба варианта являются водонепроницаемыми, однако им серьезно относятся ко всем дополнительным вызовам функций, поэтому я склонен использовать вариант 1, однако вариант 2 будет более «истинным ООП» имхо.

http://fabien.potencier.org/article/47/pragmatism-over-theory-protected-vs-private Также читайте, который также предполагает вариант 2:/

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

+0

Вариант 3: Используйте регулярные 'public' свойства и полагайте, что другие разработчики могут читать комментарии к doc. Однако это просто вопрос дизайна, поэтому трудно сказать что-то правильно и что-то еще не так. (Sidenote: свойства OOP__theory_ определяют состояние и методы определяют поведение. В этом контексте getters/seters ошибочны, потому что доступ к свойству не является поведением) – KingCrunch

+0

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

+0

Также не существует такой вещи, как «readonly properties» в PHP, поэтому вам нужно ... (помимо магии __get, которая неявная, поэтому я предпочитаю геттер) –

ответ

4

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

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

class Foo 
{ 
    // All non-relevent code omitted 
    protected $data = NULL; 

    public class getData() 
    { 
     // Initialize the data property 
     $this -> data = array(); 
     // Populate the data property with a DB query 
     $query = $this -> db -> prepare ('SELECT * FROM footable;'); 
     if ($query -> execute()) 
     { 
      $this -> data = $query -> fetchAll(); 
     } 
     return ($this -> data); 
    } 

    public function doSomethingWithData() 
    { 
     $this -> getData() 
     foreach ($this -> data as $row) 
     { 
      // Do processing here 
     } 
    } 
} 

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

class Bar 
{ 
    // All non-relevent code omitted 
    protected $data = NULL; 

    public class getData() 
    { 
     // Only run the enclosed if the data property isn't initialized 
     if (is_null ($this -> data)) 
     { 
      // Initialize the data property 
      $this -> data = array(); 
      // Populate the data property with a DB query 
      $query = $this -> db -> prepare ('SELECT * FROM footable;'); 
      if ($query -> execute()) 
      { 
       $this -> data = $query -> fetchAll(); 
      } 
     } 
     return ($this -> data); 
    } 

    public function doSomethingWithData() 
    { 
     foreach ($this -> getData() as $row) 
     { 
      // Do processing 
     } 
    } 
} 

В этой версии, вы можете вызвать doSomethingWithData (и действительно GetData) так часто, как вам нравится, вы никогда не будете запускать более одного поиска в базе данных. Кроме того, если getData и doSomethingWithData никогда не вызываются, поиск базы данных никогда не выполняется. Это приведет к большому выигрышу в производительности, поскольку поиск базы данных будет дорогостоящим и его следует избегать, когда это возможно.

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

+0

«Лучшая практика имеет тенденцию благоприятствовать правильному если результат не будет по-настоящему страдать из-за этого ». Жаль, что я могу только +1 раз – adlawson

+0

Но вызов getData() изнутри считается лучшей практикой с вашей точки зрения, не так ли? Почему _data определяется как защищенная по прагматическим причинам? –

+0

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

Смежные вопросы