Pull to refresh

Getters/Setters getting real

Reading time 4 min
Views 7.3K
Достаточно много видел разных вариантов реализации возможностей которые есть в обычных ОО языках (Delphi, Java, ActionScript) — и которых частенько не хватает php. А именно get & set методы.

В данном топике предлагаю очень простую и эффективную реализацию, которая не содержит ничего лишнего и в тоже время прекрасно реализовывает get/set функционал, позволяющий скрыть сами переменные и в тоже время сделать их read only, write only || read-write.

Дальше больше

Код исходного объекта:

class Object {
   
   public function getClass(){
      return get_class($this);
   }
   
   public function __get($name){
      $getterMethod='get'.$name;
      
      if(method_exists($this,$getterMethod)){
         return $this->$getterMethod();
      }elseif(property_exists($this,$name)){
         $backtrace=debug_backtrace();
         
         trigger_error(
            sprintf('Cannot access protected property %s::$%s in <b>%s</b> on line <b>%s</b>',$this->getClass(),$name,$backtrace[0]['file'],$backtrace[0]['line'])
            ,E_USER_ERROR);
      }else{
         $backtrace=debug_backtrace();
         
         trigger_error(
            sprintf('<b>Notice</b>: Undefined property: %s::$%s in <b>%s</b> on line <b>%s</b>',$this->getClass(),$name,$backtrace[0]['file'],$backtrace[0]['line'])
            ,E_USER_ERROR);
      }
      
      return NULL;
   }
   
   public function __set($name,$value){
      $setterMethod='set'.$name;
      
      if(method_exists($this,$setterMethod)){
         $this->$setterMethod($value);
      }elseif(property_exists($this,$name)){
         $backtrace=debug_backtrace();
         
         trigger_error(
            sprintf('Cannot access protected property %s::$%s in <b>%s</b> on line <b>%s</b>',$this->getClass(),$name,$backtrace[0]['file'],$backtrace[0]['line'])
            ,E_USER_ERROR);
      }else{
         $backtrace=debug_backtrace();
         
         trigger_error(
            sprintf('<b>Notice</b>: Undefined property: <b>%s</b>::$<b>%s</b> in <b>%s</b> on line <b>%s</b>',$this->getClass(),$name,$backtrace[0]['file'],$backtrace[0]['line'])
            ,E_USER_ERROR);
      }
   }
}
* This source code was highlighted with Source Code Highlighter.


Таким образом, класс наследующий данный — автоматически получает функциональную возможность
использования get/set методов, при этом нет необходимости переопределять какие либо методы в наследующих классах.

Из плюсов


  • Простота
  • Минимальная избыточность
  • Hint: Сами методы get&set можно сделать как public, так и protected — от этого будет зависеть — возможен ли будет их вызов напрямую (Ex. в случае public — помимо возможности $obj->height=444; будет возможность вызвать метод напрямую $obj->setHeight(444) )


Из минусов


  • В силу особенностей видимости переменных и методов (public|protected|private) — данные конструкции не работают с методами и переменными типа private


Пример:



class Rectangle extends Object {
   
   protected $width=400;
   protected $height=1;
   
   protected function getWidth(){
      return $this->width;
   }
  
   protected function getHeight(){
      return $this->height;
   }
  
   public function setHeight($value){
      $this->height=$value;
   }
  
   protected function getArea(){
      return $this->width*$this->height;
   }
}
 
$rect=new Rectangle();

echo $rect->width.'*'.$rect->height.'='.$rect->area."<br />\n";

$rect->height=1000;

echo $rect->width.'*'.$rect->height.'='.$rect->area."<br />\n";

$rect->area=500;
* This source code was highlighted with Source Code Highlighter.


В приведенном примере Вы можете заметить, что свойство «ширина» является read-only, в то время как
«высота» read-write + установить высоту можно 2мя способами.
И есть еще одно свойство «area»(площадь), которое является виртуальным, но в тоже время может быть вызвано как $rect->area;

P.S. Вот и мой первый «кирпичик» на хабре :)
Tags:
Hubs:
-1
Comments 50
Comments Comments 50

Articles