Home >Backend Development >PHP Tutorial >php面向对象方法实例详解

php面向对象方法实例详解

怪我咯
怪我咯Original
2017-07-11 11:48:502549browse

面向对象编程(OOP)是我们编程的一项基本技能,PHP5对OOP提供了良好的支持。如何使用OOP的思想来进行PHP的高级编程,对于提高PHP编程能力和规划好Web开发构架都是非常有意义的。下面我们就通过实例来说明使用PHP的OOP进行编程的实际意义和应用方法。

  我们通常在做一个有数据库后台的网站的时候,都会考虑到程序需要适用于不同的应用环境。和其他编程语言有所不同的是,在PHP中,操作数据库的是一系列的具体功能函数(如果你不使用ODBC接口的话)。这样做虽然效率很高,但是封装却不够。如果有一个统一的数据库接口,那么我们就可以不对程序做任何修改而适用于多种数据库,从而使程序的移植性和跨平台能力都大大提高。

一、php面向对象的简单列子
以人为列子:

<?phpheader("Content-type: text/html; charset=utf-8");class person{//下面是人的成员属性var $name;//人的名字var $sex;//人的性别var $age;//人的年龄//定义一个构造方法参数为姓名$name,性别$sex和年龄$agefunction construct($name,$sex,$age){//通过构造方法传进来的$name给成员属性$this->name赋初始值$this->name=$name;//通过构造方法传进来的$sex给成员属性$this->sex赋初始值$this->sex=$sex;//通过构造方法传进来的$age给成员属性$this->age赋初始值$this->age="$age";
}//下面是人的成员方法function say()//这个人可以说话的方法
{echo "我的名字叫:".$this->name."性别;".$this->sex."我的年龄是:".$this->age."<br>";
}function run() //这个人可以走路的方法
{echo "这个人在走路";
}//这是一个析构函数,在对象销毁前调用function destruct(){echo "再见".$this->name."<br>";
}
}//通过构造方法创建3个对象$p1,$p2,$p3,分别传入三个不同的实参为姓名性别和年龄$p1=new person("小明","男",20);$p2=new person("熊","女",30);$p3=new person("向日葵","男",25);$p1->say();$p2->say();$p3->say();//下面访问3个对象的说话方式$p1->say();$p2->say();$p3->say();?>

二、php面向对象的几个步骤
第一类的定义:

<?php
  Class myobject{
    //……}?>

第二成员方法:

<?phpclassmyobject{   function getobjectname($name){
      echo "商品名称为:".$name;
   }
}?>

第三类的实例化:

<?phpclass myobject{
  function getobjectname($name){
     echo "商品名称为:".$name;
   }
}$c_book=new myobject();           //实例化对象echo $c_book->getobjectname("计算机图书");  //调用getbookname()方法?>

第四成员变量:

<?phpclass myobject{
  public $object_name;
  functionsetobjectname($name){    $this->object_name=$name;
  }
  functiongetobjectname(){    return$this->object_name;
  }
}$c_book=new myobject();$c_book->setobjectname("计算机图书");echo $c_book->object_name."<br>";echo $c_book->getobjectname();?>

第五常量类:
既然有变量,当然也会有常量了。常量就是不会改变的量,是一个恒值。众所周知的一个常量就是圆周率Pi。定义常量使用关键字const如:
ConstPI=3.14159;
例:

<?phpclass myobject{                        
  const book_type="计算机图书";             //声明常量book_type
  public $object_name;                                    //声明变量
  functionsetobjectname($name){                     //声明方法setobjectname()
      $this->object_name=$name;                       //设置成员的变量值
  }
  functiongetobjectname(){                //声明方法getobject()
    return$this->object_name;                        
  }
}$c_book=new myobject();                                 //实例化对象$c_book->setobjectname("PHP的类");              //调用方法setobjectnameecho myobject::book_type."<br>";              //输出常量的值echo $c_book->getobjectname();                 //调用方法getobjectname?>

第六面向对象类的构造方法

<?phpclass myobject{                        
   public $object_name;   //商品名称
   public $object_price;              //商品价格
   public $object_num;        //商品数量
   public $object_agio;        //商品折扣
   …………
}            
?>

声明一个myobject类的对象,并对这个类的一些成员变量赋初值。代码如下:

<?php
class myobject{                        
   public $object_name;   public $object_price;   public $object_num;   public $object_agio;
   functiongetobjectname(){      return$this->object_name;        return$this->object_price;        return $this->object_num;        return $this->object_agio;
   }
}         
$dress=new myobject();$dress->object_name="western-style clothes";$dress->object_price=1500;$dress->object_num=5;$dress->object_agio=8;
echo $dress->getobjectname();  
?>Voidconstruect([mixed args,[……]])

注意:函数中的是两条下划线,不是一条。
实例2:

<?phpclass myobject{                        
  public $object_name;  public $object_price;  public $object_num;  public $object_agio;
functionconstruct($name,$price,$num,$agio){   //通过参数给成员变量赋值
      $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
   }function setobjectname($name){
    $this->object_name=$name;
}function getobjectname1(){
    return $this->object_name;
}function getobjectname2(){
        return $this->object_price;
}
}            
$c_book=new myobject("western-styleclothes",1500,5,8);echo $c_book->getobjectname1();echo "<br>";echo $c_book->getobjectname2();?>

第七析构方法:
概念
析构方法的作用和构造方法正好相反,是对象被销毁时被调用的,作用是释放内存。析构方法的格式为:
Voiddestruct(void)
例:

<?phpclass myobject{                        
  public $object_name;  public $object_price;  public $object_num;  public $object_agio;
functionconstruct($name,$price,$num,$agio){   //通过参数给成员变量赋值
      $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
   }function setobjectname($name){
    $this->object_name=$name;
}function getobjectname1(){
    return $this->object_name;
}function getobjectname2(){
        return $this->object_price;
}function destruct(){
  echo "<p><b>对象被销毁,调用析构函数。</b></p>";
}
}            
$c_book=new myobject("western-styleclothes",1500,5,8);echo $c_book->getobjectname1();echo "<br>";echo $c_book->getobjectname2();unset($c_book);?>

PHP使用的是一种“垃圾回收”机制,自动清除不再使用的对象,释放内存。就是说即使不使用unset函数,析构方法也会自动被调用,这里只是明确一下析构函数在何时被调用。一般情况下是不需要手动创建析构方法的。

<?phpclass myobject{                        
   public $object_name;   public $object_price;   public $object_num;   public $object_agio;function construct($name,$price,$num,$agio){    //通过参数给成员变量赋值
       $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
  }function setobjectname($name){
    $this->object_name=$name;
}function getobjectname1(){
     return$this->object_name;
}function getobjectname2(){
        return $this->object_price;
}function destruct(){
   echo"<p><b>对象被销毁,调用析构函数。</b></p>";
}
}            
$c_book=new myobject("western-styleclothes",1500,5,8);echo $c_book->getobjectname1();echo "<br>";echo $c_book->getobjectname2();?>

第八继承和多状态的实现

Class subclass extends superclass{
   ……
}

说明:subclass为子类的名称,superclass为父类名称。
例:

<?phpclass myobject{                        
  public $object_name;  public $object_price;  public $object_num;  public $object_agio;
functionconstruct($name,$price,$num,$agio){   //通过参数给成员变量赋值
      $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
   }function showme(){
    echo "这句话会输出吗?答案是不会。";
}
}class book extends myobject{         
   public $book_type;
       functionconstruct($type,$num){         $this->book_type=$type;         $this->object_num=$num;  
       }
       functionshowme(){                            //重写父类中的showme()方法。
         return "本次新进".$this->book_type."图书".$this->object_num."本"."<br>";
       }
}class elec extends myobject{
   function showme(){                             //重写父类中的showme()方法
         return "热卖商品:".$this->object_name."<br>"."原 价:".$this->object_price."<br>"."特 价".$this->object_price*$this->object_agio;
       }
}$c_book=new book("计算机类",1000);   //声明一个book子类对象。$h_elec=new elec("待机王XX系列",1200,3,0.8);    //声明一个elec子类对象。echo$c_book->showme()."<br>";   //输出book子类的showme()方法echo $h_elec->showme();          //输出elec子类的是showme()方法?>

子类继承了父类的所有成员变量和方法,包括构造函数。这就是继承的实现。
当子类被创建时,PHP会先在子类中查找构造方法。如果子类有自己的构造方法,PHP会先调用子类中的方法,当子类中没有时,PHP则会去调用父类中的构造方法。
两个子类重写了父类的方法showme(),所以两个对象虽然调用的都是showme()方法,但返回的却是两段不同的信息。这就是多态性的实现。

第九

this->
在 前面类的实例化中,对如何调用成员方法有了基本的了解,那就是用对象名加方法名,格式为“对象名->方法名”。但在定义类时(如 myobject),根本无法得知对象的名称是什么。这时如果调用类中的方法,就要用伪变量

this的意思就是本身,所 以$this->只可以在类的内部使用。
例:


<?phpclassexample{   //创建类example
  function exam(){   //创建成员方法
     if(isset($this)){            //判断变量$this是否存在
           echo "\$this的值为:".get_class($this);    //如果存在,输出$this所属类的名字
        }else{           echo "$this未定义。";
        }
  }
}$class_name=newexample();   //实例化对象$class_name->exam();          //调用方法exam()?>

Get_class函数返回对象所属类的名字,如果不是对象,则返回false。
2、操作符::
相比伪变量$this只能在类的内部使用,操作符::可是真正的强大。操作符::可以在没有声明任何实例的情况下访问类中的成员方法和成员变量。使用::操作符的通用格式为:
      关键字::变量名/常量名/方法名
这里的关键字分为3种情况:
Parent关键字:可以调用父类中的成员变量、成员方法和常量。
Self关键字:可以调用当前类中的静态成员和常量。
类名:可以调用本类中的变量、常量和方法。
例:

   <?phpclass book{const name="conputer";      //声明常量namefunction construct(){        //构造方法
     echo "本月图书类冠军为:".book::name."<br>";   //输出默认值
  }
}class l_book extends book{          //book类的子类
  const name="foreign language";      //声明常量
  function construct(){                  //子类的构造方法
     parent::construct();       //调用父类的构造方法
         echo "本月图书类冠军为:".self::name;    //输出本类中的默认值
   }
}$obj=new l_book();?>

说明:关于静态方法(变量)的声明及使用可参考以下内容。

第十公共、私有和保护
1、 public公共成员
顾名思义,就是可以公开的、没有必要隐藏的数据信息。可以在程序的任何地点(类内、类外)被其他的类和对象调用。子类可以继承和使用父类中所有的公共成员。
所有的变量都被声明为public,而所有的方法在默认的状态下也是public。所以对变量
和方法的调用显示得十分混乱。为了解决这个问题,就需要使用第二个关键字:private。
2、 private私有成员
被private关键字修饰的变量和方法,只能在所属类的内部被调用和修改,不可以在类外被访问。在子类中也不可以。
例:

<?phpclass book{private $name="computer";public function setname($name){
   $this->name=$name;
  }public function getname(){
   return $this->name;
  }
}class lbook extends book{}$lbook=new lbook();echo "正确操作私有变量的方法:";$lbook->setname("PHP应用开发!");echo $lbook->getname();echo "直接操作私有变量的结果:";echo book:name;?>

对于成员方法,如果没有写关键字,那么默认就是public。从本节开始,以后所有的方法及变量都会带个关键字,这是一种良好的书写习惯。
3、 protected保护成员
private 关键字可以将数据完全隐藏起来,除了在本类外,其他地方都不可以调用。子类也不可以。但对于有些变量希望子类能够调用,但对另外的类来说,还要做到封装。 这时,就可以使用protected。被protected修改的类成员,可以在类和子类中被调用,其他地方则不可以被调用。
例:

<?phpclass book{
  protected $name="computer";
}class lbook extends book{
  public function showme(){
      echo "对于protected修饰的变量,在子类中是可以直接调用的。如:\$name=".$this->name."<br>";
   }
}$lbook=new lbook();$lbook->showme();echo "但在其他的地方是不可以调用的,否则:";$lbook->name="history";?>

第十一  PHP对象的高级应用
1.        final关键字
final,中文含义是最终的、最后的。被final修饰过的类和方法就是“最终版本”;
如果有一个类的格式为:

  Final class class_name{}

说明该类不可以再被继承,也不能再有子类。
如果有一个方法的格式为:
Final function method_name();
说明该方法在子类中不可以进行重写,也不可以被覆盖。
例:

<?phpfinal class myobject{
  function construct(){
      echo "initialize object";
   }
}class mybook extends myobject{
  static function exam(){
      echo "you can&#39;t see me.";
   }
}
mybook::exam();?>

输出的结果是:

Fatal error: Class mybookmay not inherit from final class (myobject) in C:\webserver\wwwroot\2.phpon line 19
  1. 抽象类
    抽象类是一种不能被实例化的类,只能作为其他类的父类来使用。抽象类使用abstract关键字来声明,格式为:

    Abstract class abstractname{}

抽象类和普通类相似,都包含成员变量、成员方法。两者的区别在于,抽象类至少要包含一个抽象方法。抽象方法没有方法体,其功能的实现只能在子类中完成。抽象方法也是使用abstract关键字修饰的。它的格式为:
Abstractfunction abstractname();
注意:在抽象方法后面要有分号“;”
抽象类和抽象方法主要应用于复杂的层次关系中,这种层次关系要求每一个子类都包含并重写某些特定的方法。举一个例子:中国的美食是多种多样的,有吉菜、鲁菜、川菜、粤菜等。每种菜系使用的都是煎、炒、炸等手法,只是在具体的步骤上,各有各的不同。如果把中国美食当作一个大类cate,下面的各大菜系就是cate的子类,而煎炒烹炸则是每个类中都有的方法。每个方法在子类中的实现都是不同的,在父类中无法规定。为了统一规范,不同子类的方法要有一个相同的方法名:decoct(煎)、stir_fry(炒)、cook(烹)、fry(炸)。
例:

<?php
    /* 抽象类myobject */
        abstract class myobject{    //抽象方法servie
            abstract functionservice($getname,$price,$num);
        }        //声明抽象类的子类mybook
        class mybook extends myobject{    //实现抽象方法service
            function service($getname,$price,$num){
                  echo "您购买的商品是".$getname.",该商品的价格是:".$price."元";                      echo "您购买的数量为:".$num."本。";                      echo "如发现缺页、损坏、请在3日内更换。";
               }
        }        //声明另一个抽象类的子类mycomputer
        class mycomputer extends myobject{   //实现抽象方法service
            function service($getname,$price,$num){
                  echo "您购买的商品是:".$getname.",该商品的价格是:".$price."元。";                      echo "您购买的数量为:".$num."台。";                      echo "如发生非人为质量问题,请在3个月内更换。";
               }
        }        $book=new mybook();    //实例化对象$book
        $computer=new mycomputer();   //实例化对象$computer
        $book->service("《PHP从入门到精通》",85,3);   //调用$book对象的service方法
        echo "<br />";   
        $computer->service("XX笔记本",8500,1);    //调用computer对象的service方法?>
  1. 接口的使用
    继承特性简化了对象、类的创建,增加了代码的可重性。但PHP只支持单继承。如果想实现多重继承,就要使用接口。PHP可以实现多个接口。
    接口类通过interface关键字来声明,并且类中只能包含未实现的方法和一些成员变量,格式如下:

Interface interfacename{
  Function interfacename1();
  Function interfacename2();
  ………………
}

注意:不要用public以外的关键字来修饰接口中的类成员,对于方法,不写关键字也可以。这是一个接口类自身的天性决定的。
子类是通过implements关键字来实现接口的,如果要实现多个接口,那么每个接口之间使用逗号“,”连接。而且所有未实现的方法需要在子类中全部实现,否则PHP将会出现错误。格式如下:

Class subclass implementsinterfacename1,interfacename2{
    Function interfacename1(){
       //功能实现
     }    Function interfacename2(){
       //功能实现
     }
     …………
}

例:本例首先声明了两个接口mpopedom和mpurview,接着声明了两个类member和manager,其中member类继承了mpopedom接口;manager继承了mpopedom和mpurview接口。分别实现各自的成员方法后,实例化两个对象

manager。最后调用实现的方法。


<?php
     interface mpopedom{
           function popedom();
        }        interface mpurview{
           function purview();
        }        class member implements mpurview{
            function purview(){
                    echo "会员拥有的权限";
                }
        }        class manager implements mpurview,mpopedom{
            function purview(){
                echo "管理员拥有会员的全部权限。";
                }                function popedom(){
                    echo "管理员还有会员没有的权限。";
                }
        }        $member=new member();        $manager=new manager();        $member->purview();        echo "<br />";        $manager->purview();        $manager->popedom();?>

通过上面的实例可以发现,抽象类和接口实现的功能十分相似。抽象类的优点是可以在抽象类中实现公共的方法,而接口则可以实现多继承。至于何时使用抽象类和接口就要看具体实现了。
4.        克隆对象
  (1)、克隆对象
   在PHP4中,对象被当作普通的数据类型来使用。如果想引开对象,需要使用&来声明,否则会按照PHP4的默认方式来按值传递对象。
例:本实例首先实例化一个myobject类的对象

book1的默认值是book,然后将对象

book2赋值。改变

book1的值。


   <?php
     classmyobject{             private $object_type="book";               public function settype($type){
                   $this->object_type=$type;  
                }               public function gettype(){
                   return $this->object_type;
                }
        }        $book1=new myobject();        $book2=$book1;        $book2->settype("computer");        echo "对象\$book1的值为:".$book1->gettype();?>

上面的实例,在PHP5中的返回值为:对象

book2只是

book1的值为:book,因为对象

book1的一个备份。
在PHP5中如果需要将对象复制,也就是克隆一个对象。需要使用关键字clone来实现。克隆一个对象的格式为:


     $object1=new classname();     $object2=clone $object1;
 (2)、clone()方法

有时除了单纯地克隆对象外,还需要克隆出来的对象可以拥有自己的属性和行为。这时就可以使用_clone()方法来实现。clone()方法的作用是:在克隆对象的过程中,调用_clone()方法,可以使用克隆出来的对象保持自己的一些行为及属性。
例:

<?php
     class myobject{
             private $object_type="book";                 public function settype($type){
                      $this->object_type=$type;
                 }                 public function gettype(){
                      return $this->object_type;
                 }                 public function clone(){
                     $this->object_type="computer";
                                            }      
        }        $book1=new myobject();        $book2=clone $book1;        echo "对象$book1的变量值为:".$book1->gettype();        echo"<br />";        echo "对象$book2的变量值为:".$book2->gettype();?>
  1. 对象比较
    通过克隆对象,相信读者已经理解表达式

    object1和

    object1所表示的不同含义。但在实际开发中,应如何判断两个对象之间的关系是克隆还是引用?
    这是可以使用比较运算符==和===。两个等号是比较两个对象的内容,3个等号===是比较对象的引用地址。
    例:

<?php
     classmyobject{            private $name;               function construct($name){
                   $this->name=$name;
                }
        }        $book=new myobject(book);        $clonebook=clone $book;        $referbook=$book;        if($clonebook==$book){            echo "两个对象的内容相等。<br />";
        }        if($referbook===$book){            echo "两个对象的引用地址相等。<br />";
        }?>
  1. 对象类型检测
    Instanceof操作符可以检测当前对象是属于哪个类的。一般格式如为:
    Objectname instanceof classname
    例:本实例首先创建两个类,一个基类(myobject)与一个子类(mybook)。实例化一个子类对象,判断对象是否属于该子类,再判断对象是否属于基类。
    例:

<?php
     classmyobject{}        class mybook extends myobject{
            private $type;
     }        $cbook=new mybook();        if($cbook instanceof mybook){            echo "对象\$cbook属于mybook类<br />";
        }        if($cbook instanceof myobject){            echo "对象\$book属于myobject类<br />";
        }?>
  1. 魔术方法(_)
    PHP中有很多以两个下划线开头的方法,如前面已经介绍过的construct()、destruct()和clone(),这些方法被称为魔术方法。下在我们将学习其他一些魔术方法。
    注意:PHP中保留了所有以””开头的方法,所以只能使用在PHP文档中有的这些方法,不要自己创建。
    (1)、set()和get()方法
    这两个魔术方法的作用为:
    当程序试图写入一个不存在或不可见的成员变量时,PHP就会执行set()方法。set()方法包含两个参数,分别表示变量名称和变量值。两个参数不可省略。
    当程序调用一个未定义或不可见的成员变量时,可以通过get()方法来读取变量值。get()方法有一个参数,表示要调用的变量名。
    注意:如果希望PHP调用这些魔术方法,那么首先必须在类中进行定义;否则PHP不会执行未创建的魔术方法。
    例:

<?php
     class myobject{
           private $type="";               private function get($name){
                  if(isset($this->$name)){                        echo "变量".$name."的值为:".$this->$name."<br />";
                     }                     else{                        echo "变量".$name."未定义,初始化为0<br />";                            $this->$name=0;
                     }
               }               private function set($name,$value){
                   if(isset($this->$name)){                         $this->$name=$value;                             echo "变量".$name."赋值为:".$value."<br />";
                      }else{                          $this->$name=$value;                             echo "变量".$name."被初始化为:".$value."<br />";
                      }
               }
        }        $mycomputer=new myobject();        $mycomputer->type="DIY";        $mycomputer->type;        $mycomputer->name;?>

(2)、call()方法
call()方法的作用是:当程序试图调用不存在或不可见的成员方法时,PHP会先调用call()方法来存储方法名及其参数。call()方法包含两个参数,即方法名和方法参数。其中,方法参数是以数组形式存在的。
例:

<?php
     class myobject{
            public function mydream(){
                     echo "调用的方法存在,直接执行此方法:<br />";
                }                public function call($method,$parameter){
                     echo "如果方法不存在,则执行call()方法。<br/>";                       echo "方法名为:".$method."<br />";                       echo "参数有:";
                       var_dump($parameter);
                }
        }        $exam=new myobject();        $exam->mydream();        $exam->mdreadm(&#39;how&#39;,&#39;what&#39;,&#39;why&#39;);?>

(3)、sleep()和wakeup()方法
使用serialize()函数可以实现序列化对象。就是将对象中的变量全部保存下来,对象中的类则只保存类名。在使用serialize()函数时,如果实例化的对象包含sleep()方法,则会执行sleep()方法。该方法可以清除对象并返回一个该对象中所有变量的数组。使用sleep()方法的目的是关闭对象可能具有的数据库连接等类似的善后工作。
Unserialize()函数可以重新还原一个被serialize()函数序列化的对象,wakeup()方法则是恢复在序列化中可能丢失的数据库连接及相关工作。
例:

<?php
     class myobject{
           private $type="DIY";               public function gettype(){
                   return $this->type;
               }               public function sleep(){
                   echo "使用serialize()函数将对象保存起来,可以存放到文本文件、数据库等地方。<br />";                      return $this;
               }               public function wakeup(){
                   echo "当需要该数据时,使用unserialize()函数对已序列化的字符串进行操作,将其转换回来对象。<br />";
               }
        }       $mybook=new myobject();       $i=serialize($mybook);       echo "序列化后的字符串:".$i."<br />";       $rebook=unserialize($i);       echo "还原后的成员变量:".$rebook->gettype();?>

(4)、tostring()方法
魔术方法这个作用是:当使用echo 或print输出对象时,将对象转化为字符串。
例:

<?php
     class myobject{
            private $type="DIY";                public function tostring(){
                    return $this->type;
                }
        }        $mycomputer=new myobject();        echo "对象\$mycomputer的值为:";        echo $mycomputer;?>

(5)、autoload()方法
   将一个独立、完整的类保存到一个PHP页中,并且文件名和类名保持一致,这是每个开发人员者需要养成的良好习惯。这样,在下次重复使用某个类时即能很轻易地找到它。但还有一个问题是让开发人员头疼不已的,如果要在一个页面中引进很多的类,需要使用include_once()函数或require_once()函数一个一个地引入。
   PHP5解决了这个问题,autoload()方法可以自动实例化需要使用的类。当程序要用到一个类,但该类还没有被实例化时,PHP5将使用autoload()方法,在指定的路径下自动查找和该类名称相同的文件。如果找到,程序则继续执行,否则,报告错误。
例:
Myobject.class.php页面代码如下:

<?php
     classmyobject{              private $cont;                public function construct($cont){
                    $this->cont=$cont;
                }                public function tostring(){
                    return $this->cont;
                }
        }?>

Index.php页面代码如下:

<?php
     functionautoload($class_name){                                  $class_path=$class_name.&#39;.class.php&#39;;                                    if(file_exists($class_path)){                                       include_once($class_path);
                                    }else{                                       echo "类路径错误。";
                                    }
                              }                              $mybook=new myobject("江山代有人才出    各领风骚数百年");                              echo $mybook;?>

一、php面向对象的简单列子
以人为列子:

<?phpheader("Content-type: text/html; charset=utf-8");class person{//下面是人的成员属性var $name;//人的名字var $sex;//人的性别var $age;//人的年龄//定义一个构造方法参数为姓名$name,性别$sex和年龄$agefunction construct($name,$sex,$age){//通过构造方法传进来的$name给成员属性$this->name赋初始值$this->name=$name;//通过构造方法传进来的$sex给成员属性$this->sex赋初始值$this->sex=$sex;//通过构造方法传进来的$age给成员属性$this->age赋初始值$this->age="$age";
}//下面是人的成员方法function say()//这个人可以说话的方法
{echo "我的名字叫:".$this->name."性别;".$this->sex."我的年龄是:".$this->age."<br>";
}function run() //这个人可以走路的方法
{echo "这个人在走路";
}//这是一个析构函数,在对象销毁前调用function destruct(){echo "再见".$this->name."<br>";
}
}//通过构造方法创建3个对象$p1,$p2,$p3,分别传入三个不同的实参为姓名性别和年龄$p1=new person("小明","男",20);$p2=new person("熊","女",30);$p3=new person("向日葵","男",25);$p1->say();$p2->say();$p3->say();//下面访问3个对象的说话方式$p1->say();$p2->say();$p3->say();?>

二、php面向对象的几个步骤
第一类的定义:

<?php
  Class myobject{
    //……}?>

第二成员方法:

<?phpclassmyobject{   function getobjectname($name){
      echo "商品名称为:".$name;
   }
}?>

第三类的实例化:

<?phpclass myobject{
  function getobjectname($name){
     echo "商品名称为:".$name;
   }
}$c_book=new myobject();           //实例化对象echo $c_book->getobjectname("计算机图书");  //调用getbookname()方法?>

第四成员变量:

<?phpclass myobject{
  public $object_name;
  functionsetobjectname($name){    $this->object_name=$name;
  }
  functiongetobjectname(){    return$this->object_name;
  }
}$c_book=new myobject();$c_book->setobjectname("计算机图书");echo $c_book->object_name."<br>";echo $c_book->getobjectname();?>

第五常量类:
既然有变量,当然也会有常量了。常量就是不会改变的量,是一个恒值。众所周知的一个常量就是圆周率Pi。定义常量使用关键字const如:
ConstPI=3.14159;
例:

<?phpclass myobject{                        
  const book_type="计算机图书";             //声明常量book_type
  public $object_name;                                    //声明变量
  functionsetobjectname($name){                     //声明方法setobjectname()
      $this->object_name=$name;                       //设置成员的变量值
  }
  functiongetobjectname(){                //声明方法getobject()
    return$this->object_name;                        
  }
}$c_book=new myobject();                                 //实例化对象$c_book->setobjectname("PHP的类");              //调用方法setobjectnameecho myobject::book_type."<br>";              //输出常量的值echo $c_book->getobjectname();                 //调用方法getobjectname?>

第六面向对象类的构造方法

<?phpclass myobject{                        
   public $object_name;   //商品名称
   public $object_price;              //商品价格
   public $object_num;        //商品数量
   public $object_agio;        //商品折扣
   …………
}            
?>

声明一个myobject类的对象,并对这个类的一些成员变量赋初值。代码如下:

<?php
class myobject{                        
   public $object_name;   public $object_price;   public $object_num;   public $object_agio;
   functiongetobjectname(){      return$this->object_name;        return$this->object_price;        return $this->object_num;        return $this->object_agio;
   }
}         
$dress=new myobject();$dress->object_name="western-style clothes";$dress->object_price=1500;$dress->object_num=5;$dress->object_agio=8;
echo $dress->getobjectname();  
?>Voidconstruect([mixed args,[……]])

注意:函数中的是两条下划线,不是一条。
实例2:

<?phpclass myobject{                        
  public $object_name;  public $object_price;  public $object_num;  public $object_agio;
functionconstruct($name,$price,$num,$agio){   //通过参数给成员变量赋值
      $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
   }function setobjectname($name){
    $this->object_name=$name;
}function getobjectname1(){
    return $this->object_name;
}function getobjectname2(){
        return $this->object_price;
}
}            
$c_book=new myobject("western-styleclothes",1500,5,8);echo $c_book->getobjectname1();echo "<br>";echo $c_book->getobjectname2();?>

第七析构方法:
概念
析构方法的作用和构造方法正好相反,是对象被销毁时被调用的,作用是释放内存。析构方法的格式为:
Voiddestruct(void)
例:

<?phpclass myobject{                        
  public $object_name;  public $object_price;  public $object_num;  public $object_agio;
functionconstruct($name,$price,$num,$agio){   //通过参数给成员变量赋值
      $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
   }function setobjectname($name){
    $this->object_name=$name;
}function getobjectname1(){
    return $this->object_name;
}function getobjectname2(){
        return $this->object_price;
}function destruct(){
  echo "<p><b>对象被销毁,调用析构函数。</b></p>";
}
}            
$c_book=new myobject("western-styleclothes",1500,5,8);echo $c_book->getobjectname1();echo "<br>";echo $c_book->getobjectname2();unset($c_book);?>

PHP使用的是一种“垃圾回收”机制,自动清除不再使用的对象,释放内存。就是说即使不使用unset函数,析构方法也会自动被调用,这里只是明确一下析构函数在何时被调用。一般情况下是不需要手动创建析构方法的。

<?phpclass myobject{                        
   public $object_name;   public $object_price;   public $object_num;   public $object_agio;function construct($name,$price,$num,$agio){    //通过参数给成员变量赋值
       $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
  }function setobjectname($name){
    $this->object_name=$name;
}function getobjectname1(){
     return$this->object_name;
}function getobjectname2(){
        return $this->object_price;
}function destruct(){
   echo"<p><b>对象被销毁,调用析构函数。</b></p>";
}
}            
$c_book=new myobject("western-styleclothes",1500,5,8);echo $c_book->getobjectname1();echo "<br>";echo $c_book->getobjectname2();?>

第八继承和多状态的实现

Class subclass extends superclass{
   ……
}

说明:subclass为子类的名称,superclass为父类名称。
例:

<?phpclass myobject{                        
  public $object_name;  public $object_price;  public $object_num;  public $object_agio;
functionconstruct($name,$price,$num,$agio){   //通过参数给成员变量赋值
      $this->object_name=$name;          $this->object_price=$price;          $this->object_num=$num;          $this->object_agio=$agio;
   }function showme(){
    echo "这句话会输出吗?答案是不会。";
}
}class book extends myobject{         
   public $book_type;
       functionconstruct($type,$num){         $this->book_type=$type;         $this->object_num=$num;  
       }
       functionshowme(){                            //重写父类中的showme()方法。
         return "本次新进".$this->book_type."图书".$this->object_num."本"."<br>";
       }
}class elec extends myobject{
   function showme(){                             //重写父类中的showme()方法
         return "热卖商品:".$this->object_name."<br>"."原 价:".$this->object_price."<br>"."特 价".$this->object_price*$this->object_agio;
       }
}$c_book=new book("计算机类",1000);   //声明一个book子类对象。$h_elec=new elec("待机王XX系列",1200,3,0.8);    //声明一个elec子类对象。echo$c_book->showme()."<br>";   //输出book子类的showme()方法echo $h_elec->showme();          //输出elec子类的是showme()方法?>

子类继承了父类的所有成员变量和方法,包括构造函数。这就是继承的实现。
当子类被创建时,PHP会先在子类中查找构造方法。如果子类有自己的构造方法,PHP会先调用子类中的方法,当子类中没有时,PHP则会去调用父类中的构造方法。
两个子类重写了父类的方法showme(),所以两个对象虽然调用的都是showme()方法,但返回的却是两段不同的信息。这就是多态性的实现。

第九

this->
在 前面类的实例化中,对如何调用成员方法有了基本的了解,那就是用对象名加方法名,格式为“对象名->方法名”。但在定义类时(如 myobject),根本无法得知对象的名称是什么。这时如果调用类中的方法,就要用伪变量

this的意思就是本身,所 以$this->只可以在类的内部使用。
例:


<?phpclassexample{   //创建类example
  function exam(){   //创建成员方法
     if(isset($this)){            //判断变量$this是否存在
           echo "\$this的值为:".get_class($this);    //如果存在,输出$this所属类的名字
        }else{           echo "$this未定义。";
        }
  }
}$class_name=newexample();   //实例化对象$class_name->exam();          //调用方法exam()?>

Get_class函数返回对象所属类的名字,如果不是对象,则返回false。
2、操作符::
相比伪变量$this只能在类的内部使用,操作符::可是真正的强大。操作符::可以在没有声明任何实例的情况下访问类中的成员方法和成员变量。使用::操作符的通用格式为:
      关键字::变量名/常量名/方法名
这里的关键字分为3种情况:
Parent关键字:可以调用父类中的成员变量、成员方法和常量。
Self关键字:可以调用当前类中的静态成员和常量。
类名:可以调用本类中的变量、常量和方法。
例:

   <?phpclass book{const name="conputer";      //声明常量namefunction construct(){        //构造方法
     echo "本月图书类冠军为:".book::name."<br>";   //输出默认值
  }
}class l_book extends book{          //book类的子类
  const name="foreign language";      //声明常量
  function construct(){                  //子类的构造方法
     parent::construct();       //调用父类的构造方法
         echo "本月图书类冠军为:".self::name;    //输出本类中的默认值
   }
}$obj=new l_book();?>

说明:关于静态方法(变量)的声明及使用可参考以下内容。

第十公共、私有和保护
1、 public公共成员
顾名思义,就是可以公开的、没有必要隐藏的数据信息。可以在程序的任何地点(类内、类外)被其他的类和对象调用。子类可以继承和使用父类中所有的公共成员。
所有的变量都被声明为public,而所有的方法在默认的状态下也是public。所以对变量
和方法的调用显示得十分混乱。为了解决这个问题,就需要使用第二个关键字:private。
2、 private私有成员
被private关键字修饰的变量和方法,只能在所属类的内部被调用和修改,不可以在类外被访问。在子类中也不可以。
例:

<?phpclass book{private $name="computer";public function setname($name){
   $this->name=$name;
  }public function getname(){
   return $this->name;
  }
}class lbook extends book{}$lbook=new lbook();echo "正确操作私有变量的方法:";$lbook->setname("PHP应用开发!");echo $lbook->getname();echo "直接操作私有变量的结果:";echo book:name;?>

对于成员方法,如果没有写关键字,那么默认就是public。从本节开始,以后所有的方法及变量都会带个关键字,这是一种良好的书写习惯。
3、 protected保护成员
private 关键字可以将数据完全隐藏起来,除了在本类外,其他地方都不可以调用。子类也不可以。但对于有些变量希望子类能够调用,但对另外的类来说,还要做到封装。 这时,就可以使用protected。被protected修改的类成员,可以在类和子类中被调用,其他地方则不可以被调用。
例:

<?phpclass book{
  protected $name="computer";
}class lbook extends book{
  public function showme(){
      echo "对于protected修饰的变量,在子类中是可以直接调用的。如:\$name=".$this->name."<br>";
   }
}$lbook=new lbook();$lbook->showme();echo "但在其他的地方是不可以调用的,否则:";$lbook->name="history";?>

第十一  PHP对象的高级应用
1.        final关键字
final,中文含义是最终的、最后的。被final修饰过的类和方法就是“最终版本”;
如果有一个类的格式为:

  Final class class_name{}

说明该类不可以再被继承,也不能再有子类。
如果有一个方法的格式为:
Final function method_name();
说明该方法在子类中不可以进行重写,也不可以被覆盖。
例:

<?phpfinal class myobject{
  function construct(){
      echo "initialize object";
   }
}class mybook extends myobject{
  static function exam(){
      echo "you can&#39;t see me.";
   }
}
mybook::exam();?>

输出的结果是:

Fatal error: Class mybookmay not inherit from final class (myobject) in C:\webserver\wwwroot\2.phpon line 19
  1. 抽象类
    抽象类是一种不能被实例化的类,只能作为其他类的父类来使用。抽象类使用abstract关键字来声明,格式为:

    Abstract class abstractname{}

抽象类和普通类相似,都包含成员变量、成员方法。两者的区别在于,抽象类至少要包含一个抽象方法。抽象方法没有方法体,其功能的实现只能在子类中完成。抽象方法也是使用abstract关键字修饰的。它的格式为:
Abstractfunction abstractname();
注意:在抽象方法后面要有分号“;”
抽象类和抽象方法主要应用于复杂的层次关系中,这种层次关系要求每一个子类都包含并重写某些特定的方法。举一个例子:中国的美食是多种多样的,有吉菜、鲁菜、川菜、粤菜等。每种菜系使用的都是煎、炒、炸等手法,只是在具体的步骤上,各有各的不同。如果把中国美食当作一个大类cate,下面的各大菜系就是cate的子类,而煎炒烹炸则是每个类中都有的方法。每个方法在子类中的实现都是不同的,在父类中无法规定。为了统一规范,不同子类的方法要有一个相同的方法名:decoct(煎)、stir_fry(炒)、cook(烹)、fry(炸)。
例:

<?php
    /* 抽象类myobject */
        abstract class myobject{    //抽象方法servie
            abstract functionservice($getname,$price,$num);
        }        //声明抽象类的子类mybook
        class mybook extends myobject{    //实现抽象方法service
            function service($getname,$price,$num){
                  echo "您购买的商品是".$getname.",该商品的价格是:".$price."元";                      echo "您购买的数量为:".$num."本。";                      echo "如发现缺页、损坏、请在3日内更换。";
               }
        }        //声明另一个抽象类的子类mycomputer
        class mycomputer extends myobject{   //实现抽象方法service
            function service($getname,$price,$num){
                  echo "您购买的商品是:".$getname.",该商品的价格是:".$price."元。";                      echo "您购买的数量为:".$num."台。";                      echo "如发生非人为质量问题,请在3个月内更换。";
               }
        }        $book=new mybook();    //实例化对象$book
        $computer=new mycomputer();   //实例化对象$computer
        $book->service("《PHP从入门到精通》",85,3);   //调用$book对象的service方法
        echo "<br />";   
        $computer->service("XX笔记本",8500,1);    //调用computer对象的service方法?>
  1. 接口的使用
    继承特性简化了对象、类的创建,增加了代码的可重性。但PHP只支持单继承。如果想实现多重继承,就要使用接口。PHP可以实现多个接口。
    接口类通过interface关键字来声明,并且类中只能包含未实现的方法和一些成员变量,格式如下:

Interface interfacename{
  Function interfacename1();
  Function interfacename2();
  ………………
}

注意:不要用public以外的关键字来修饰接口中的类成员,对于方法,不写关键字也可以。这是一个接口类自身的天性决定的。
子类是通过implements关键字来实现接口的,如果要实现多个接口,那么每个接口之间使用逗号“,”连接。而且所有未实现的方法需要在子类中全部实现,否则PHP将会出现错误。格式如下:

Class subclass implementsinterfacename1,interfacename2{
    Function interfacename1(){
       //功能实现
     }    Function interfacename2(){
       //功能实现
     }
     …………
}

例:本例首先声明了两个接口mpopedom和mpurview,接着声明了两个类member和manager,其中member类继承了mpopedom接口;manager继承了mpopedom和mpurview接口。分别实现各自的成员方法后,实例化两个对象

manager。最后调用实现的方法。


<?php
     interface mpopedom{
           function popedom();
        }        interface mpurview{
           function purview();
        }        class member implements mpurview{
            function purview(){
                    echo "会员拥有的权限";
                }
        }        class manager implements mpurview,mpopedom{
            function purview(){
                echo "管理员拥有会员的全部权限。";
                }                function popedom(){
                    echo "管理员还有会员没有的权限。";
                }
        }        $member=new member();        $manager=new manager();        $member->purview();        echo "<br />";        $manager->purview();        $manager->popedom();?>

通过上面的实例可以发现,抽象类和接口实现的功能十分相似。抽象类的优点是可以在抽象类中实现公共的方法,而接口则可以实现多继承。至于何时使用抽象类和接口就要看具体实现了。
4.        克隆对象
  (1)、克隆对象
   在PHP4中,对象被当作普通的数据类型来使用。如果想引开对象,需要使用&来声明,否则会按照PHP4的默认方式来按值传递对象。
例:本实例首先实例化一个myobject类的对象

book1的默认值是book,然后将对象

book2赋值。改变

book1的值。


   <?php
     classmyobject{             private $object_type="book";               public function settype($type){
                   $this->object_type=$type;  
                }               public function gettype(){
                   return $this->object_type;
                }
        }        $book1=new myobject();        $book2=$book1;        $book2->settype("computer");        echo "对象\$book1的值为:".$book1->gettype();?>

上面的实例,在PHP5中的返回值为:对象

book2只是

book1的值为:book,因为对象

book1的一个备份。
在PHP5中如果需要将对象复制,也就是克隆一个对象。需要使用关键字clone来实现。克隆一个对象的格式为:


     $object1=new classname();     $object2=clone $object1;
 (2)、clone()方法

有时除了单纯地克隆对象外,还需要克隆出来的对象可以拥有自己的属性和行为。这时就可以使用_clone()方法来实现。clone()方法的作用是:在克隆对象的过程中,调用_clone()方法,可以使用克隆出来的对象保持自己的一些行为及属性。
例:

<?php
     class myobject{
             private $object_type="book";                 public function settype($type){
                      $this->object_type=$type;
                 }                 public function gettype(){
                      return $this->object_type;
                 }                 public function clone(){
                     $this->object_type="computer";
                                            }      
        }        $book1=new myobject();        $book2=clone $book1;        echo "对象$book1的变量值为:".$book1->gettype();        echo"<br />";        echo "对象$book2的变量值为:".$book2->gettype();?>
  1. 对象比较
    通过克隆对象,相信读者已经理解表达式

    object1和

    object1所表示的不同含义。但在实际开发中,应如何判断两个对象之间的关系是克隆还是引用?
    这是可以使用比较运算符==和===。两个等号是比较两个对象的内容,3个等号===是比较对象的引用地址。
    例:

<?php
     classmyobject{            private $name;               function construct($name){
                   $this->name=$name;
                }
        }        $book=new myobject(book);        $clonebook=clone $book;        $referbook=$book;        if($clonebook==$book){            echo "两个对象的内容相等。<br />";
        }        if($referbook===$book){            echo "两个对象的引用地址相等。<br />";
        }?>
  1. 对象类型检测
    Instanceof操作符可以检测当前对象是属于哪个类的。一般格式如为:
    Objectname instanceof classname
    例:本实例首先创建两个类,一个基类(myobject)与一个子类(mybook)。实例化一个子类对象,判断对象是否属于该子类,再判断对象是否属于基类。
    例:

<?php
     classmyobject{}        class mybook extends myobject{
            private $type;
     }        $cbook=new mybook();        if($cbook instanceof mybook){            echo "对象\$cbook属于mybook类<br />";
        }        if($cbook instanceof myobject){            echo "对象\$book属于myobject类<br />";
        }?>
  1. 魔术方法(_)
    PHP中有很多以两个下划线开头的方法,如前面已经介绍过的construct()、destruct()和clone(),这些方法被称为魔术方法。下在我们将学习其他一些魔术方法。
    注意:PHP中保留了所有以””开头的方法,所以只能使用在PHP文档中有的这些方法,不要自己创建。
    (1)、set()和get()方法
    这两个魔术方法的作用为:
    当程序试图写入一个不存在或不可见的成员变量时,PHP就会执行set()方法。set()方法包含两个参数,分别表示变量名称和变量值。两个参数不可省略。
    当程序调用一个未定义或不可见的成员变量时,可以通过get()方法来读取变量值。get()方法有一个参数,表示要调用的变量名。
    注意:如果希望PHP调用这些魔术方法,那么首先必须在类中进行定义;否则PHP不会执行未创建的魔术方法。
    例:

<?php
     class myobject{
           private $type="";               private function get($name){
                  if(isset($this->$name)){                        echo "变量".$name."的值为:".$this->$name."<br />";
                     }                     else{                        echo "变量".$name."未定义,初始化为0<br />";                            $this->$name=0;
                     }
               }               private function set($name,$value){
                   if(isset($this->$name)){                         $this->$name=$value;                             echo "变量".$name."赋值为:".$value."<br />";
                      }else{                          $this->$name=$value;                             echo "变量".$name."被初始化为:".$value."<br />";
                      }
               }
        }        $mycomputer=new myobject();        $mycomputer->type="DIY";        $mycomputer->type;        $mycomputer->name;?>

(2)、call()方法
call()方法的作用是:当程序试图调用不存在或不可见的成员方法时,PHP会先调用call()方法来存储方法名及其参数。call()方法包含两个参数,即方法名和方法参数。其中,方法参数是以数组形式存在的。
例:

<?php
     class myobject{
            public function mydream(){
                     echo "调用的方法存在,直接执行此方法:<br />";
                }                public function call($method,$parameter){
                     echo "如果方法不存在,则执行call()方法。<br/>";                       echo "方法名为:".$method."<br />";                       echo "参数有:";
                       var_dump($parameter);
                }
        }        $exam=new myobject();        $exam->mydream();        $exam->mdreadm(&#39;how&#39;,&#39;what&#39;,&#39;why&#39;);?>

(3)、sleep()和wakeup()方法
使用serialize()函数可以实现序列化对象。就是将对象中的变量全部保存下来,对象中的类则只保存类名。在使用serialize()函数时,如果实例化的对象包含sleep()方法,则会执行sleep()方法。该方法可以清除对象并返回一个该对象中所有变量的数组。使用sleep()方法的目的是关闭对象可能具有的数据库连接等类似的善后工作。
Unserialize()函数可以重新还原一个被serialize()函数序列化的对象,wakeup()方法则是恢复在序列化中可能丢失的数据库连接及相关工作。
例:

<?php
     class myobject{
           private $type="DIY";               public function gettype(){
                   return $this->type;
               }               public function sleep(){
                   echo "使用serialize()函数将对象保存起来,可以存放到文本文件、数据库等地方。<br />";                      return $this;
               }               public function wakeup(){
                   echo "当需要该数据时,使用unserialize()函数对已序列化的字符串进行操作,将其转换回来对象。<br />";
               }
        }       $mybook=new myobject();       $i=serialize($mybook);       echo "序列化后的字符串:".$i."<br />";       $rebook=unserialize($i);       echo "还原后的成员变量:".$rebook->gettype();?>

(4)、tostring()方法
魔术方法这个作用是:当使用echo 或print输出对象时,将对象转化为字符串。
例:

<?php
     class myobject{
            private $type="DIY";                public function tostring(){
                    return $this->type;
                }
        }        $mycomputer=new myobject();        echo "对象\$mycomputer的值为:";        echo $mycomputer;?>

(5)、autoload()方法
   将一个独立、完整的类保存到一个PHP页中,并且文件名和类名保持一致,这是每个开发人员者需要养成的良好习惯。这样,在下次重复使用某个类时即能很轻易地找到它。但还有一个问题是让开发人员头疼不已的,如果要在一个页面中引进很多的类,需要使用include_once()函数或require_once()函数一个一个地引入。
   PHP5解决了这个问题,autoload()方法可以自动实例化需要使用的类。当程序要用到一个类,但该类还没有被实例化时,PHP5将使用autoload()方法,在指定的路径下自动查找和该类名称相同的文件。如果找到,程序则继续执行,否则,报告错误。
例:
Myobject.class.php页面代码如下:

<?php
     classmyobject{              private $cont;                public function construct($cont){
                    $this->cont=$cont;
                }                public function tostring(){
                    return $this->cont;
                }
        }?>

Index.php页面代码如下:

<?php
     functionautoload($class_name){                                  $class_path=$class_name.&#39;.class.php&#39;;                                    if(file_exists($class_path)){                                       include_once($class_path);
                                    }else{                                       echo "类路径错误。";
                                    }
                              }                              $mybook=new myobject("江山代有人才出    各领风骚数百年");                              echo $mybook;?>

The above is the detailed content of php面向对象方法实例详解. For more information, please follow other related articles on the PHP Chinese website!

Statement:
The content of this article is voluntarily contributed by netizens, and the copyright belongs to the original author. This site does not assume corresponding legal responsibility. If you find any content suspected of plagiarism or infringement, please contact admin@php.cn