PHP面向对象深入理解之三(类中的魔术方法)
通常情况下,不建议使用魔术方法,因为会增加opcode,影响程序的性能。
1. __toString
通常你使用print 打印一个类的时候,你会发现打印出来的类似于 Object id#1
的id句柄,如果我们不想得到这样的句柄,那我们可以改写__toString 方法
class A
{
private $name = 'A class';
public function __construct($name)
{
$this->name = $name;
}
public function __toString()
{
return $this->name;
}
}
$a = new A('a');
$b = new A('b');
print $a;
print $b;
2. __set 和__get
__get方法是某个成员变量不能存在的时候,访问会报错,可以通过设置__get,避免报错,通常与__set配合使用
__set则是无此变量时,可以设置默认加入方式,让__get能访问到
class A
{
private $data = null;
public function __get($name)
{
return isset($this->data[$name])?$this->data[$name]:'';
}
public function __set($name,$value)
{
$this->data[$name] = $value;
}
}
$a = new A();
$a->age = 13;
print $a->age;
3. __sleep 和 __wakeup
__sleep 用于对象serialize序列化的时候,准备序列化需要的资源
它必须返回的是当前类的成员变量的名字组成的数组
__wakeup 则相反,在对象unserilize反序列化的时候 会优先执行的操作
class A
{
public $name = 'zhansan';
public function __sleep()
{
return array('name');
}
public function __wakeup()
{
echo 'bbb';
}
public function geta()
{
echo 'a is running ';
}
}
$a = new A();
$astr = serialize($a); //注意一个对象被序列化的时候 他的方法和功能依然被保留
print $astr; //只是暴露给外界的很少
$newa = unserialize($a); //反序列化的时候 就被重新激活了会优先调用__wakeup
$newa->geta(); //不信,你看 仍然能调用
打印结果:O”A”
{s
”name”;s
”zhansan”;}bbba is running
4.__invoke
当尝试以调用函数的方式,调用一个对象的时候,__invoke就被激活了
class A
{
public function __invoke($argvs)
{
var_dump($argvs);
}
}
$a = new A();
$a('obj is called');
打印: string(13) “obj is called”
5. __call 和 __callStatic(5.3.0以后)
当对象调用一个不存在的方法时,会自动触发__call方法
而调用一个不存在的静态方法时,会自动触发__callStatic
<?php
class A
{
public function __call($funcname,$argvs)
{
echo 'call:';
var_dump($funcname,$argvs);
}
public static function __callStatic($funcname,$argvs)
{
echo 'call static:';
var_dump($funcname,$argvs);
}
}
$a = new A();
A::runaaa('abc');
$a->getbbb('111');
打印结果:
call static:string(6) “runaaa”
array(1) {
[0]=>
string(3) “abc”
}
call:string(6) “getbbb”
array(1) {
[0]=>
string(3) “111”
}
6. __isset 和 __unset
对象的不存在属性或不可访问属性调用 isset()和empty() 方法 __isset 会被触发
unset() 则触发 __unset
class A
{
private $data = array();
public function __get($name)
{
return $this->data[$name];
}
public function __set($name,$value)
{
$this->data[$name] = $value ;
}
public function __isset($name)
{
echo 'isset:';
return isset($this->data[$name]);
}
public function __unset($name)
{
echo 'unset:'
unset($this->data[$name]);
}
}
$a = new A();
$a->name='aa';
var_dump(isset($a->name));
unset($a->name);
var_dump(isset($a->name));
打印结果:
isset:bool(true)
unsetbool(false)
7. __clone
当调用clone 操作符来复制一个新对象时,会触发__clone 方法
如果,对象的某些属性是使用的引用的方式,新对象仍然会因为旧对象的改变而改变;
class A
{
public $name = 'lisi';
public $obj = null;
public function __clone()
{
echo 'clone is called';
$this->name = 'lisi'; //这里做一些初始化操作
$this->obj = clone $this->obj; //做深度拷贝
}
}
$a = new A();
$a->name = 'zhao';
$b = clone $a;
var_dump($b->name);
var_dump($a->name);
$c= new A();
$a->obj = $c;
打印:
clone is calledstring(4) “lisi”
string(4) “zhao”
还没有评论,来说两句吧...