zoukankan      html  css  js  c++  java
  • PHP面向对象(四)

    引子:

     1 <?php 
     2         //值传递
     3         $a=10;
     4         $b=$a;  //将变量a的值取出复制一份赋给变量b
     5         $b=20;
     6         echo $a;    //10
     7 
     8         //引用传递
     9         $a=10;
    10         $b=&$a;  //为变量a起个别名b
    11         $b=20;
    12         echo $a;    //20
    13     ?>

       由引子程序可以看到,当使用"="号时是值传递,两个变量相对独立,改变其中一个,另一个不会发生影响;当在变量前加上"&"符时,变成引用传递,相当于取别名,根本是还是同一个东西。但是当变量属于对象类型时,使用"="号时就变成了引用传递(资源类型也是),想达到"值传递"的效果,就可以使用克隆技术(只能用在对象类型)。

    一、克隆
      在PHP中可以根据现有的对象克隆出一个完全一样的对象,克隆以后,原来和副本两个对象完全独立、互不干扰。在PHP5中使用clone关键字克隆对象。

     1 <?php 
     2     class Person {}
     3     $p1=new Person();   //创建一个对象
     4     $p2=$p1;            //这不是复制对象,而是为对象多复制一个访问该对象的引用
     5     $p3=clone $p1;      //克隆(复制)一个对象的副本
     6     
     7     var_dump($p1);  //object(Person)[1]
     8     var_dump($p2);  //object(Person)[1]    $p2和$p1是同一个对象
     9     var_dump($p3);  //object(Person)[2]
    10  ?>

      魔术方法"__clone()":该方法是在对象克隆时自动调用的,所以就可以通过此方法对克隆后的副本重新初始化。__clone()方法不需要任何参数,该方法中自动包含$this对象的引用,$this是副本对象的引用。
      通过克隆技术我们可以方便的得到一个类型的对象,但是当此对象中包括资源或者子对象时又如何呢?

     1 <?php 
     2 //测试
     3 $f = new File("./a.txt");
     4 echo $f->read()."<br/>";        //aaaaaaaaaaa
     5 echo $f->read()."<br/>";        //bbbbbbbbbbb 
     6 echo $f->read()."<br/>";        //ccccccccccc
     7 
     8 $f2 = clone $f;
     9 //unset($f);
    10 echo $f2->read()."<br/>";       //ddddddddddd
    11 
    12 var_dump($f);       //object(File)[1]private 'filename' => string './a.txt' (length=7)private 'link' => resource(3, stream)
    13 var_dump($f2);      //object(File)[2]private 'filename' => string './a.txt' (length=7)private 'link' => resource(3, stream)
    14 
    15 
    16 //自定义一个文件读取类
    17 class File
    18 {
    19     private $filename;
    20     private $link=null;
    21     
    22     public function __construct($filename)
    23     {
    24         $this->filename = $filename;
    25         $this->link = fopen($this->filename,"r");
    26     }
    27     
    28     public function __destruct()
    29     {
    30         if($this->link != null){
    31             @fclose($this->link);
    32         }
    33     }
    34     //魔术方法
    35    /* public function __clone()
    36     {
    37         $this->link = fopen($this->filename,"r");
    38     }*/
    39     
    40     public function read()
    41     {
    42         return fgets($this->link);
    43     }
    44     
    45 }
    46 ?>

      当对象中包括资源或者子对象时,克隆并不能完全实现对象$f和对象$f2完全相对独立!!
      当打开魔术方法__clone()此时var_dump()结果呢?
        object(File)[1]private 'filename' => string './a.txt' (length=7)private 'link' => resource(3, stream)
        object(File)[1]private 'filename' => string './a.txt' (length=7)private 'link' => resource(4, stream)
      可以看到,link属性的资源号是不同的,此时对象$f和$f2完全相对独立。

    二、魔术方法:__tostring()方法
      当直接输出一个对象时,会尝试调用当前对象的__toString()方法,若没有则报错。
       注意:__toString()魔术方法必须返回一个字串值。

     1 <?php
     2     class Stu
     3     {
     4         private $name="zhangsan";
     5         private $age=20;
     6         
     7         public function __toString()
     8         {
     9             return $this->name.":".$this->age;
    10         }
    11     }
    12 
    13     $s = new Stu();
    14     echo $s; 
    15 ?>

    三、魔术方法:__call方法
      如果尝试调用一个不存在的方法,则会调用此方法。需要两个参数:第一个参数是调用不存在方法时,接收这个方法的名称字符串;而第二个参数则以数组的形式传递到__call()方法的第二个参数中。

     1 <?php
     2     class A
     3     {
     4         public function fun1()
     5         {
     6             echo "fun1()....<br/>";
     7         }
     8         public function fun2()
     9         {
    10             echo "fun2()....<br/>";
    11         }
    12         public function __call($method,$params)
    13         {
    14            echo "你调用的{$method}方法不存在!参数: ";
    15            print_r($params);
    16            echo "<br/>";
    17         }
    18     }
    19 
    20 $a = new A();
    21 $a->fun1();             //fun1()....
    22 $a->fun2();             //fun2()....
    23 $a->fun3(100,200);      //你调用的fun3方法不存在!参数: Array ( [0] => 100 [1] => 200 ) 
    24 $a->add("aa","bb","cc");//你调用的add方法不存在!参数: Array ( [0] => aa [1] => bb [2] => cc )
    25 ?>

    四、自动加载类
      当你尝试使用一个PHP没有组织到的类时,它会寻找一个名为__autoload()的全局函数(不是在类中声明的函数)如果存在这个函数,PHP会用一个参数来调用它,参数即类的名称。

     1 <?php
     2     //当实例化使用一个不存在的类时,此函数会自动调用,并将类传入,
     3     function __autoload($classname)
     4     {
     5         //拼装文件
     6         $fname = $classname.".PHP";
     7         if(file_exists($fname)){
     8             require($fname);
     9         }
    10     }
    11 
    12     //测试学生类
    13 
    14     //require("./Stu.php");
    15 
    16 
    17     $stu = new Stu("王五",23);
    18     echo $stu;      //王五:23
    19 ?>      

    五、对象串行化(在对象持久化存储、和传输中使用)
      对象也是一种在内存中存储的数据类型,它的寿命通常随着该对象的程序终止而终止。而对象通过写出描述自己状态的数值来记录自己,这个过程称为对象的串行化(Serialization):
        a.对象需要在网络中传输时,将对象串行化成二进制字符串后再网络中传输;
        b.对象需要持久保存时,将对象串行化后写入文件或数据库中。

      serialize() -- 串行化
      unserialize() -- 反串行化
      php里面的值都可以使用函数serialize()来返回一个包含字节流的字符串来表示。
                  unserialize()函数能够重新把字符串变回php原来的值。
      序列化一个对象将会保存对象的所有变量,但是不会保存对象的方法,只会保存类的名字。

      由于串行化就像克隆一样,虽然对象被串行化但是对象内的资源或子对象是不能被串行化的
      魔术方法:
        __sleep():是执行串行化时自动调用的方法,目的是实现资源类型的属性实关闭操作
          注意:sleep方法需要返回一个数组,其中数组中的值是串行化时要保留的属性名
        __wakeup():是在执行反串行化时自动调用的方法,目的是实现资源属性的打开(sleep方法关闭的资源)

     1 <?php
     2 //串行化和反串行化中的魔术方法__sleep()  __wakeup()
     3 $f = new File("a.txt");
     4 
     5 $s = serialize($f); 
     6 
     7 echo $s;
     8 
     9 $ob = unserialize($s);
    10 
    11 echo $ob->read()."<br/>";
    12 echo $ob->read()."<br/>";
    13 echo $ob->read()."<br/>";
    14 
    15 
    16 //自定义一个文件读取类
    17 class File
    18 {
    19     private $filename;
    20     private $link=null;
    21     
    22     public function __construct($filename)
    23     {
    24         $this->filename = $filename;
    25         $this->link = fopen($this->filename,"r");
    26     }
    27     
    28     public function __destruct()
    29     {
    30         if($this->link != null){
    31             @fclose($this->link);
    32         }
    33     }
    34     
    35     //当此对象串行化时会自动调用此方法
    36     public function __sleep()
    37     {
    38         return array("filename"); //返回需要保留的字段名(串行化时)
    39     }
    40     
    41     //当此对象反串行化时会自动调用此方法
    42     public function __wakeup()
    43     {
    44        $this->link = fopen($this->filename,"r"); 
    45     }
    46     
    47     public function read()
    48     {
    49         return fgets($this->link);
    50     }
    51     
    52 }
    53 ?>

    六、类型约束
      类型约束可以使用的类型是:数组或对象
      若指定的一个类名,那么可传入本类及子类的对象进去。
      可以使用的约束类型:(复合类型)数组array,类名、抽象类名、接口名

     1 <?php
     2 //类型约束:目前支持的为数组和对象
     3 
     4 //此函的参数必须为数组类型
     5 function fun(array $a){
     6     echo "数组长度:".count($a)."<br/>";
     7 }
     8 
     9 fun([10,20,30,40]);
    10 fun([10,20,30,40,50]);
    11 //fun("aaaaaaaaaa"); //参数必须为一个数组
    12 
    13 
    14 class A{}
    15 class B extends A{}
    16 class C{}
    17 demo(new A());
    18 demo(new B());
    19 demo(new C()); //此处不可以,参数非法
    20 
    21 //此函数的参数类型必须为A类的对象,或子类对象
    22 function demo(A $ob)
    23 {
    24     echo "正常调用<br/>";
    25 }
    26 ?>

    七、对象连贯操作

     1 <?php
     2 //对象的连贯操作
     3 
     4 class Demo
     5 {
     6     private $a = array();
     7     
     8     public function put($v)
     9     {
    10         $this->a[] = $v;
    11         return $this;
    12     }
    13     
    14     public function __toString()
    15     {
    16         return implode(",",$this->a);
    17     } 
    18 }
    19 //测试
    20 $d = new Demo();
    21 $d->put("aaa");     
    22 $d->put("bbb");    
    23 $d->put("ccc");     
    24 echo $d;        //aaa,bbb,ccc
    25 
    26 $dd = new Demo();
    27 echo $dd->put("1111")->put("2222")->put("3333");    //1111,2222,3333
  • 相关阅读:
    【交往智慧】005.做一个愿意聆听的人
    【生活智慧】005.信守诺言的约束
    人生时间表. 如果您有了时间
    爱情五十七课,还是两个人
    【生活智慧】008.不要把自己的不顺归结于外在因素
    【交往智慧】006.勇于接受别人的意见
    【交往智慧】001.交际本领可使你利用外界的无限能量
    【交往智慧】007.给人改过的机会
    【生活智慧】004.把手放在《圣经》上
    【交往智慧】003.要能与人和谐相处
  • 原文地址:https://www.cnblogs.com/yexiang520/p/5661993.html
Copyright © 2011-2022 走看看