Blogger Information
Blog 22
fans 1
comment 0
visits 20218
Popular Tutorials
More>
Latest Downloads
More>
Web Effects
Website Source Code
Website Materials
Front End Template
0214作业(1)-闭包与对象绑定和自定义异常类基础知识-php培训十期线上班
Dseven
Original
637 people have browsed it

1. 闭包与对象绑定

1.1 bind()绑定方法

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

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

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

    1.2 bindto()绑定方法

    1. //命名空间
    2. namespace php\demo\part1;
    3. use Closure;
    4. //空行
    5. //首先定义一个用来演示的类
    6. class Youth
    7. {
    8. public $name;
    9. static $gender = 'female';
    10. protected $age = 18;
    11. private $weight = 50;
    12. public function show(){
    13. //非静态成员是通过this关键字和->结合来访问,因此public和private属性访问方法相同
    14. return $this->name.'的性别是'.self::$gender.',今年'.$this->age.'岁,体重有'.$this->weight.'Kg';
    15. }
    16. }
    17. class user extends Youth{
    18. //....
    19. }
    20. //定义一个匿名函数,这个函数先尝试修改类中静态成员gender的值,并将实例化对象中各成员的值输出
    21. $setValueFun = function (){
    22. self::$gender = 'male';
    23. //因为这个函数将要和类绑定,绑定后就像类中已经定义的一个方法一样,因此在代码中要用$this->name来访问类中的属性
    24. return $this->name.'的性别是'.self::$gender.',今年'.$this->age.'岁,体重有'.$this->weight.'Kg';
    25. };
    26. //将Youth类实例出一个对象,并给各赋值
    27. $obj = new user();
    28. $obj->name = 'Lily';
    29. //再实例化一个对象,用来对比
    30. $obj1 = new user();
    31. $obj1->name = 'Lucy';
    32. //bindto()是Closure类中的一个方法,其返回值是个匿名函数。
    33. //该方法第一参数代表要绑定的类的一个实例,换个角度看就是说匿名函数中的this代表哪个实例化的对象,也就是this取值是多少。
    34. //该方法第二个参数代表类作用域,在使用的时候就是用绑定类的类名。
    35. //示例一:演示调用父类和子类的区别,会发现在调用子类时private属性因为不能继承,而无法显示
    36. $newSetValueFun =$setValueFun->bindto($obj,'php\demo\part1\Youth');
    37. echo $newSetValueFun();
    38. echo '<br>';
    39. //输出Lily的性别是male,今年18岁,体重有50Kg
    40. $newSetValueFun =$setValueFun->bindto($obj,'php\demo\part1\user');
    41. echo $newSetValueFun();
    42. echo '<br>';
    43. //输出Lily的性别是male,今年18岁,体重有Kg,发现这里的体重没有了
    44. //示例二:演示调用不同对象时,得到的结果不一样
    45. $newSetValueFun =$setValueFun->bindto($obj,'php\demo\part1\Youth');
    46. echo $newSetValueFun();
    47. echo '<br>';
    48. //输出Lily的性别是male,今年18岁,体重有50Kg
    49. $newSetValueFun =$setValueFun->bindto($obj1,'php\demo\part1\Youth');
    50. echo $newSetValueFun();
    51. echo '<br>';
    52. //输出Lucy的性别是male,今年18岁,体重有50Kg
    53. //你会发现虽然$obj和$obj1都是子类user实例化出来的对象,但是因为bingto()中最后一个参数都是Youth类,所以private属性weight的值还是能显示出来
    54. //同时,因为$obj和$obj1中对name属性赋值不一样,也导致最后输出的结果不一样。
  • 补充知识
    • 类中static成员在内存中是有且唯有一个固定地址的,不因实例化出来的对象变化而变化,而类中public、protected、private成员在内存中没有固定的地址,有多少实例化的对象就有多少个。
    • bind复制一个闭包,绑定指定的 $this 对象和类作用域。把一个闭包转换为某个类的方法 (只是这个方法不需要通过对象调用), 这样闭包中的 $this、static、self 就转换成了对应的对象或类。
      • 只绑定 $this 对象.\将对象作为bind中的第二个参数,第三个参数不要。(bindto中的第一个)
      • 只绑定类作用域.\将类名作为bind中的第三个参数,第二个参数为null,相当于在类中增加了一个静态方法。(bindto中的第二个)
      • 同时绑定 $this 对象和类作用域.第二个和第三个参数都要,相当于在类中加入了一个成语方法。(bindto中的第一个和第二个)
      • 都不绑定.(这样一来只是纯粹的复制,文档说法是使用 cloning 代替 bind 或 bindTo)

ps.作业太长,分两次提交

Correcting teacher:天蓬老师天蓬老师

Correction status:qualified

Teacher's comments:成语方法? 注意错别字
Statement of this Website
The copyright of this blog article belongs to the blogger. Please specify the address when reprinting! If there is any infringement or violation of the law, please contact admin@php.cn Report processing!
All comments Speak rationally on civilized internet, please comply with News Comment Service Agreement
0 comments
Author's latest blog post