博客列表 >闭包与对象绑定和自定义异常类

闭包与对象绑定和自定义异常类

安
原创
2020年02月18日 23:00:32566浏览

bind()绑定方法

与public属性绑定

  1. namespace php\demo\part1;
  2. //空行
  3. //首先定义一个用来演示的类
  4. class Youth
  5. {
  6. public $name;
  7. public function show(){
  8. //非静态成员是通过this关键字和->结合来访问
  9. return $this->name.'是一名年轻人';
  10. }
  11. }
  12. //定义一个匿名函数,这个函数用来绑定youth类中的属性,用于设置类中属性的值,该函数接收1个$name参数
  13. $setValueFun = function ($name){
  14. //因为这个函数将要和类绑定,绑定后就像类中的一个方法,因此在代码中要用$this->name来访问类中的属性
  15. $this->name = $name;
  16. };
  17. //将Youth类实例出一个对象
  18. $obj = new Youth();
  19. //bind()是Closure类中的一个静态方法,其返回值是上面那个匿名函数的复制。
  20. //该方法第一个参数代表要准备和类绑定的匿名函数,也就是上面$setvalue代表的匿名函数。
  21. //该方法第二参数代表要绑定的类的一个实例
  22. //该方法第三个参数代表类作用域,在使用的时候就是用绑定类的类名,因为这段代码只是设置public属性,因此可以省略。
  23. //下面代码中在Closure前面加上'\'是使用的完全限定名称,代表全局命名空间,也可以用use Closure来代替
  24. $newSetValueFun = \Closure::bind($setValueFun,$obj);
  25. //还可以直接这么写,省略掉上面实例化的步骤
  26. //$newSetValueFun = Closure::bind($setValueFun,new Youth());
  27. //通过$newSetValueFun来给实例化出来的对象中的public属性$name赋值
  28. $newSetValueFun('Lucy');
  29. //调用Youth类中的show方法来验证
  30. echo $obj->show();
  31. //经验证最后输出:Lucy是一名年轻人
  32. private属性绑定(protected属性操作相同)
  33. //命名空间
  34. namespace php\demo\part1;
  35. use Closure;
  36. //空行
  37. //首先定义一个用来演示的类
  38. class Youth
  39. {
  40. private $weight;
  41. public function __toString(){
  42. //非静态成员是通过this关键字和->结合来访问,因此public和private属性访问方法相同
  43. return '一名年轻人的体重是'.$this->weight.'KG';
  44. }
  45. }
  46. //定义一个匿名函数,这个函数用来绑定youth类中的属性,用于设置类中属性的值,该函数接收2个参数
  47. $setValueFun = function ($weight){
  48. //因为这个函数将要和类绑定,绑定后就像类中已经定义的一个方法一样,因此在代码中要用$this->name来访问类中的属性
  49. $this->weight = $weight;
  50. };
  51. //将Youth类实例出一个对象
  52. $obj = new Youth();
  53. //bind()是Closure类中的一个静态方法,其返回值是上面那个匿名函数的复制。
  54. //该方法第一个参数代表要准备和类绑定的匿名函数,也就是上面$setvalue代表的匿名函数。
  55. //该方法第二参数代表要绑定的类的一个实例,换个角度看就是说匿名函数中的this代表哪个实例化的对象。
  56. //该方法第三个参数代表类作用域,在使用的时候就是用绑定类的类名。因为这里访问了类的私有成员,只有在其所在的类中才能被访问,因此必须指出类的作用域,不然就会报错。
  57. //因为使用了命名空间,而Youth作为Closure的参数,使用非限定名称会报错,应该使用完全限定或者限定名称
  58. $newSetValueFun = Closure::bind($setValueFun,$obj,'php\demo\part1\Youth');
  59. //还可以直接这么写,省略掉上面实例化的步骤
  60. //$newSetValueFun = Closure::bind($setValueFun,new Youth());
  61. //通过$newSetValueFun来给实例化出来的对象中的public属性$name赋值
  62. $newSetValueFun(45);
  63. //激活Youth类中的魔术方法__tostring()方法来验证
  64. echo $obj;
  65. //经验证最后输出:一名年轻人的体重是45KG

与static属性绑定

  1. namespace php\demo\part1;
  2. use Closure;
  3. //空行
  4. //首先定义一个用来演示的类
  5. class Youth
  6. {
  7. static $gender;
  8. public function __toString(){
  9. //非静态成员是通过this关键字和->结合来访问,因此public和private属性访问方法相同
  10. return '一名年轻人的性别是'.static::$gender;
  11. //另一种写法是
  12. //return '一名年轻人的性别是'.Youth::$gender;或者return '一名年轻人的性别是'.self::$gender
  13. }
  14. }
  15. //定义一个匿名函数,这个函数用来绑定youth类中的属性,用于设置类中属性的值,该函数接收1个参数
  16. $setValueFun = function ($gender){
  17. //因为这个函数将要和类绑定,绑定后就像类中已经定义的一个方法一样,在类中访问静态属性不能用$this,因为静态属性是所有对象共用的,只有一份,而$this代表具体的实例化对象
  18. static::$gender = $gender;
  19. };
  20. //bind()是Closure类中的一个静态方法,其返回值是上面那个匿名函数的复制。
  21. //该方法第一个参数代表要准备和类绑定的匿名函数,也就是上面$setvalue代表的匿名函数。
  22. //该方法第二参数代表要绑定的类的一个实例,换个角度看就是说匿名函数中的this代表哪个实例化的对象,因为这里访问的是静态成员,不需要实例化的对象,在这个地方可以用null。
  23. //该方法第三个参数代表类作用域,在使用的时候就是用绑定类的类名,在访问静态或者私有属性的时候必须加上这个参数。
  24. //因为使用了命名空间,而Youth作为Closure的参数,使用非限定名称会报错,应该使用完全限定或者限定名称
  25. $newSetValueFun = Closure::bind($setValueFun,null,Youth::class);
  26. //还可以直接这么写
  27. //$newSetValueFun = Closure::bind($setValueFun,null,'php\demo\part1\Youth');
  28. $newSetValueFun('female');
  29. //激活Youth类中的魔术方法__tostring()方法来验证
  30. $obj = new Youth();
  31. echo $obj;
  32. //经验证最后输出:一名年轻人的性别是female

同时访问public、private、protected和static属性,和一个public方法

  1. namespace php\demo\part1;
  2. use Closure;
  3. //空行
  4. //首先定义一个用来演示的类
  5. class Youth
  6. {
  7. public $name;
  8. static $gender;
  9. protected $age;
  10. private $weight;
  11. public function show(){
  12. //非静态成员是通过this关键字和->结合来访问,因此public和private属性访问方法相同
  13. return $this->name.'的性别是'.static::$gender.',今年'.$this->age.'岁,体重有'.$this->weight.'Kg';
  14. }
  15. }
  16. //定义一个匿名函数,这个函数用来绑定youth类中的属性,用于设置类中属性的值,该函数接收2个参数
  17. $setValueFun = function ($name,$gender,$age,$weight){
  18. //因为这个函数将要和类绑定,绑定后就像类中已经定义的一个方法一样,因此在代码中要用$this->name来访问类中的属性
  19. $this->weight = $weight;
  20. $this->age = $age;
  21. $this->name = $name;
  22. static::$gender = $gender;
  23. //通过闭包调用类中的方法
  24. echo $this->show();
  25. };
  26. //bind()是Closure类中的一个静态方法,其返回值是上面那个匿名函数的复制。
  27. //该方法第一个参数代表要准备和类绑定的匿名函数,也就是上面$setvalue代表的匿名函数。
  28. //该方法第二参数代表要绑定的类的一个实例,换个角度看就是说匿名函数中的this代表哪个实例化的对象,在这段代码中没有单独new一个对象出来,而是在参数里直接new。
  29. //该方法第三个参数代表类作用域,在使用的时候就是用绑定类的类名。因为这里访问了类的私有成员,只有在其所在的类中才能被访问,因此必须指出类的作用域,不然就会报错。
  30. //因为使用了命名空间,而Youth作为Closure的参数,使用非限定名称会报错,应该使用完全限定或者限定名称
  31. $newSetValueFun = Closure::bind($setValueFun,new Youth,'php\demo\part1\Youth');
  32. $newSetValueFun('Lucy','female',21,45);
  33. //经验证最后输出:Lucy的性别是female,今年21岁,体重有45Kg

bindto()绑定方法

  1. namespace php\demo\part1;
  2. use Closure;
  3. //空行
  4. //首先定义一个用来演示的类
  5. class Youth
  6. {
  7. public $name;
  8. static $gender = 'female';
  9. protected $age = 18;
  10. private $weight = 50;
  11. public function show(){
  12. //非静态成员是通过this关键字和->结合来访问,因此public和private属性访问方法相同
  13. return $this->name.'的性别是'.self::$gender.',今年'.$this->age.'岁,体重有'.$this->weight.'Kg';
  14. }
  15. }
  16. class user extends Youth{
  17. //....
  18. }
  19. //定义一个匿名函数,这个函数先尝试修改类中静态成员gender的值,并将实例化对象中各成员的值输出
  20. $setValueFun = function (){
  21. self::$gender = 'male';
  22. //因为这个函数将要和类绑定,绑定后就像类中已经定义的一个方法一样,因此在代码中要用$this->name来访问类中的属性
  23. return $this->name.'的性别是'.self::$gender.',今年'.$this->age.'岁,体重有'.$this->weight.'Kg';
  24. };
  25. //将Youth类实例出一个对象,并给各赋值
  26. $obj = new user();
  27. $obj->name = 'Lily';
  28. //再实例化一个对象,用来对比
  29. $obj1 = new user();
  30. $obj1->name = 'Lucy';
  31. //bindto()是Closure类中的一个方法,其返回值是个匿名函数。
  32. //该方法第一参数代表要绑定的类的一个实例,换个角度看就是说匿名函数中的this代表哪个实例化的对象,也就是this取值是多少。
  33. //该方法第二个参数代表类作用域,在使用的时候就是用绑定类的类名。
  34. //示例一:演示调用父类和子类的区别,会发现在调用子类时private属性因为不能继承,而无法显示
  35. $newSetValueFun =$setValueFun->bindto($obj,'php\demo\part1\Youth');
  36. echo $newSetValueFun();
  37. echo '<br>';
  38. //输出Lily的性别是male,今年18岁,体重有50Kg
  39. $newSetValueFun =$setValueFun->bindto($obj,'php\demo\part1\user');
  40. echo $newSetValueFun();
  41. echo '<br>';
  42. //输出Lily的性别是male,今年18岁,体重有Kg,发现这里的体重没有了
  43. //示例二:演示调用不同对象时,得到的结果不一样
  44. $newSetValueFun =$setValueFun->bindto($obj,'php\demo\part1\Youth');
  45. echo $newSetValueFun();
  46. echo '<br>';
  47. //输出Lily的性别是male,今年18岁,体重有50Kg
  48. $newSetValueFun =$setValueFun->bindto($obj1,'php\demo\part1\Youth');
  49. echo $newSetValueFun();
  50. echo '<br>';
  51. //输出Lucy的性别是male,今年18岁,体重有50Kg
  52. //你会发现虽然$obj和$obj1都是子类user实例化出来的对象,但是因为bingto()中最后一个参数都是Youth类,所以private属性weight的值还是能显示出来
  53. //同时,因为$obj和$obj1中对name属性赋值不一样,也导致最后输出的结果不一样。
声明:本文内容转载自脚本之家,由网友自发贡献,版权归原作者所有,如您发现涉嫌抄袭侵权,请联系admin@php.cn 核实处理。
全部评论
文明上网理性发言,请遵守新闻评论服务协议