Достаточно много видел разных вариантов реализации возможностей которые есть в обычных ОО языках (Delphi, Java, ActionScript) — и которых частенько не хватает php. А именно get & set методы.
В данном топике предлагаю очень простую и эффективную реализацию, которая не содержит ничего лишнего и в тоже время прекрасно реализовывает get/set функционал, позволяющий скрыть сами переменные и в тоже время сделать их read only, write only || read-write.
Дальше больше
Код исходного объекта:
Таким образом, класс наследующий данный — автоматически получает функциональную возможность
использования get/set методов, при этом нет необходимости переопределять какие либо методы в наследующих классах.
В приведенном примере Вы можете заметить, что свойство «ширина» является read-only, в то время как
«высота» read-write + установить высоту можно 2мя способами.
И есть еще одно свойство «area»(площадь), которое является виртуальным, но в тоже время может быть вызвано как $rect->area;
P.S. Вот и мой первый «кирпичик» на хабре :)
В данном топике предлагаю очень простую и эффективную реализацию, которая не содержит ничего лишнего и в тоже время прекрасно реализовывает 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. Вот и мой первый «кирпичик» на хабре :)