码迷,mamicode.com
首页 > Web开发 > 详细

PHP面向对象(四)

时间:2016-07-11 23:58:29      阅读:448      评论:0      收藏:0      [点我收藏+]

标签:

引子:

 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

 

PHP面向对象(四)

标签:

原文地址:http://www.cnblogs.com/yexiang520/p/5661993.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!