PHP面向对象深入理解之三(类中的魔术方法)

桃扇骨 2022-06-10 00:07 284阅读 0赞

通常情况下,不建议使用魔术方法,因为会增加opcode,影响程序的性能。

1. __toString

通常你使用print 打印一个类的时候,你会发现打印出来的类似于 Object id#1
的id句柄,如果我们不想得到这样的句柄,那我们可以改写__toString 方法

  1. class A
  2. {
  3. private $name = 'A class';
  4. public function __construct($name)
  5. {
  6. $this->name = $name;
  7. }
  8. public function __toString()
  9. {
  10. return $this->name;
  11. }
  12. }
  13. $a = new A('a');
  14. $b = new A('b');
  15. print $a;
  16. print $b;

2. __set 和__get

__get方法是某个成员变量不能存在的时候,访问会报错,可以通过设置__get,避免报错,通常与__set配合使用
__set则是无此变量时,可以设置默认加入方式,让__get能访问到

  1. class A
  2. {
  3. private $data = null;
  4. public function __get($name)
  5. {
  6. return isset($this->data[$name])?$this->data[$name]:'';
  7. }
  8. public function __set($name,$value)
  9. {
  10. $this->data[$name] = $value;
  11. }
  12. }
  13. $a = new A();
  14. $a->age = 13;
  15. print $a->age;

3. __sleep 和 __wakeup

__sleep 用于对象serialize序列化的时候,准备序列化需要的资源
它必须返回的是当前类的成员变量的名字组成的数组
__wakeup 则相反,在对象unserilize反序列化的时候 会优先执行的操作

  1. class A
  2. {
  3. public $name = 'zhansan';
  4. public function __sleep()
  5. {
  6. return array('name');
  7. }
  8. public function __wakeup()
  9. {
  10. echo 'bbb';
  11. }
  12. public function geta()
  13. {
  14. echo 'a is running ';
  15. }
  16. }
  17. $a = new A();
  18. $astr = serialize($a); //注意一个对象被序列化的时候 他的方法和功能依然被保留
  19. print $astr; //只是暴露给外界的很少
  20. $newa = unserialize($a); //反序列化的时候 就被重新激活了会优先调用__wakeup
  21. $newa->geta(); //不信,你看 仍然能调用

打印结果:O:1:”A”:1:{s:4:”name”;s:7:”zhansan”;}bbba is running

4.__invoke

当尝试以调用函数的方式,调用一个对象的时候,__invoke就被激活了

  1. class A
  2. {
  3. public function __invoke($argvs)
  4. {
  5. var_dump($argvs);
  6. }
  7. }
  8. $a = new A();
  9. $a('obj is called');

打印: string(13) “obj is called”

5. __call 和 __callStatic(5.3.0以后)

当对象调用一个不存在的方法时,会自动触发__call方法
而调用一个不存在的静态方法时,会自动触发__callStatic

  1. <?php
  2. class A
  3. {
  4. public function __call($funcname,$argvs)
  5. {
  6. echo 'call:';
  7. var_dump($funcname,$argvs);
  8. }
  9. public static function __callStatic($funcname,$argvs)
  10. {
  11. echo 'call static:';
  12. var_dump($funcname,$argvs);
  13. }
  14. }
  15. $a = new A();
  16. A::runaaa('abc');
  17. $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

  1. class A
  2. {
  3. private $data = array();
  4. public function __get($name)
  5. {
  6. return $this->data[$name];
  7. }
  8. public function __set($name,$value)
  9. {
  10. $this->data[$name] = $value ;
  11. }
  12. public function __isset($name)
  13. {
  14. echo 'isset:';
  15. return isset($this->data[$name]);
  16. }
  17. public function __unset($name)
  18. {
  19. echo 'unset:'
  20. unset($this->data[$name]);
  21. }
  22. }
  23. $a = new A();
  24. $a->name='aa';
  25. var_dump(isset($a->name));
  26. unset($a->name);
  27. var_dump(isset($a->name));

打印结果:
isset:bool(true)
unset:isset:bool(false)

7. __clone

当调用clone 操作符来复制一个新对象时,会触发__clone 方法
如果,对象的某些属性是使用的引用的方式,新对象仍然会因为旧对象的改变而改变;

  1. class A
  2. {
  3. public $name = 'lisi';
  4. public $obj = null;
  5. public function __clone()
  6. {
  7. echo 'clone is called';
  8. $this->name = 'lisi'; //这里做一些初始化操作
  9. $this->obj = clone $this->obj; //做深度拷贝
  10. }
  11. }
  12. $a = new A();
  13. $a->name = 'zhao';
  14. $b = clone $a;
  15. var_dump($b->name);
  16. var_dump($a->name);
  17. $c= new A();
  18. $a->obj = $c;

打印:
clone is calledstring(4) “lisi”

string(4) “zhao”

发表评论

表情:
评论列表 (有 0 条评论,284人围观)

还没有评论,来说两句吧...

相关阅读

    相关 PHP 魔术方法

    PHP 中魔术方法是以下两个划线 “\_\_” 开头的、具有特殊作用的一些方法,可以看作PHP的“语法糖”。 > 语法糖是指那些没有给计算机语言添加新功能,而只是对人类来说更