我们通常会将私有方法定义为$_pro,然后用一个set魔术方法进行修改,如下:
class A
{
private $_pro;
public function __set($pro, $val)
{
$pro = "-".$pro;
$this->$pro = $val;
}
}
通过类A的魔术set方法,只要私有变量定义为$_pro形式,那么会自动设置形如$obj->pro = $value的表达式。如果类B继承自类A,同时也会继承这个set魔术方法,如下:
class B extends A
{
private $_proInB;
}
那么,对于类B的实例,我们使用$objOfB->proInB = $value会不会设置相应的值呢?答案是否定的,因为这个表达式会首先寻找公有变量,然后寻找set方法,set方法定义在父类当中,父类的set方法,是无法访问子类的私有变量的。
这里面揭示了一个典型的场景,那就是父类的方法只能操纵父类的私有成员,而无法操纵子类的私有变量,因此,在设计父类的方法时,不要期待这个方法会对子类的私有成员产生作用。
在上面这个例子当中,如果期待无需重写set方法,就能对子类的变量进行读写,那么,可以采取的办法有两种:
1)将子类的属性定义为public,这样,父类的set方法在遇到这些变量时,会发挥多态的特性,读写子类的属性。
这种方法弊端很多,也极不规范,因此正常的类设计应当避免。
2)将类的属性读写单独设定getter和setter方法,然后在set和get魔术方法当中调用,如果我们重写类A如下:
class A
{
private $_pro;
public function getPro(){
$pro = "-".$pro;
return $this->$pro;
}
public function setPro($val){
$pro = "-".$pro;
$this->$pro=$val;
}
public function __set($pro, $val)
{
$method = 'set'.$pro;
if($method_exists($this, $method){
$this->$method($val);
}
}
}
那么,在类B当中,当设计新的私有属性时,可以设定getter和setter方法,那么就无需重定义set魔术方法了。这里的区别是,父类的set方法不能访问子类的私有成员,但是setter和getter是公共的,可以访问。