| 
 
通俗的最新PHP类的使用和归纳_[PHP教程] 一:结构和调用(实例化): 
  class className{} ,调用:$obj = new className();当类有构造函数时,还应传入参数。如$obj = new className($v,$v2...); 
  二:构造函数和析构函数:  1、构造函数用于初始化:使用__construct(),可带参数。  2、但析构函数不能带参数(用于在销去一个类之前执行一些操作或功能)。析构函数用__destruct()做名称。在脚本执行结束时,PHP会销掉内存中的对象,因此可不用析造函数,但有些比如COOKIE等,就应当要用此函数销掉。  知识点:在PHP4中也提供了构造函数,但使用的是与类同名的类方法,在PHP5仍能兼容这种做法,当一个类中没有包含__construct时,会查找与类同名的方法,如果找到,就认为是构造函数,如下:  class test  { var $b;  function test() { $this->b=5; }  function addab($c) { return $this->b+$c; }  }  $a = new test(); echo $a->addab(4); // 返回 9  3、PHP不会自动调用父类的构造函数(不支持构造函数重载),必须使用parent关键字显式地调用。  class employee{   function __construct()....  }  class Manager extents Employee{   function __construct(){   parent::_construct();   echo ’这个子类的父类构造函数调用了!’;   }  }  当然也可以调用与该实例没有任何关系的其它类的构造函数。只需在__construct()前加上类名即可。如:  otherClassName::__construct(); 
  类的主家庭成员:属性、方法、常量、静态成员 
  三、类的属性:  有两种方法对类的属性赋值或取值。  1、使用公共作用域public关键词。  2、使用__set()和__get()来分别赋值和取值,前者称为设置方法(setter)或修改方法(mutator),后者称为访问方法(accessor)或获取方法(getter)。建议使用这种方法:优点:  A、可在__set()统一进行数据验证。  B、便于统一管理属性。  注意:  第一:__set()和__get()只对私有属性起作用,对于用public定义的属性,它们两个都懒理搭理,如下:  class test{  protected $a=9,$b=2,$c;   public $d;   function __set($n,$v) { $this->$n = $v+2; }   function __get($name) { return $this->$name+2; }  }  $a = new test();  $a->b =5; echo " "; echo $a->b;  实例只对$a,$b,$c的设置会经过__set和__get过滤与返回,对于$d,就不会起作用。如$a->d=5,再返回还是5。  第二:__set($n,$v)要带两个参数。而__get($n)只能有一个参数。实例:  class test{   private $a=5,$b=6,$c;   function __set($n,$v)   {   if($n==’a’&&$n>0)   $this->$n = $v;   else   $this->$n = $v+2;   }   function __get($name)   {   return $this->$name; //如果改为return $this->$name + $this->addab(); 如调用a的值,实际返回的是a+a+b的值。默认为5+5+6=16。   }   function addab()   { return $this->a + $this->b; }  }  $e=new test();  $e->a = 11; //注意写法:类的内部用$this->$n即变量的写法,但外部实例要用$e->a的方式。  $e->b = 12; //get 14  $e->k = 22; 
  类的属性可自由扩展,如上例的k,不管是否用__set,当一个实例建立起来后,可以用$e->newProperty = xx;直接来创造一个属性,但不建议这么做。 
  四、类的方法:  理解成类当中的函数即可。  调用:  1、内部调用:可使用$this->Fanname();或$this->addab()或test::addab();  2、实例化调用时,用$e->addab();即可。对于在该方法中没有使用$this关键字的,如上例中的:  function addab() { return $this->a+$this->b; }  改为: function addab() { return 25; }那在在外部实例调用该方法,也可用“$e::addab();”或“test::addab();” 
  五、类的常量:  如果类的属性理解成类中的变量,那么类的常量和变量是不一样的,其定义方法为:  class test{   private $a;   const PI = ’3.14’;   .....   //在类中调用上面的常量用两种方法,“$this::PI”,或 “类名::PI”,这里就是test::PI,如下:   function getvalue(){   return $this->a * $this::PI; //或$this->a * test::PI,用this关键字或类名均可,但都要用双冒号。   }  }  $e= new test();  $e->PI =5; //注意,这里用 ->只是创造了一个也是名为PI的属性,而不是改变类中的PI常量的值。  echo $e::PI; //这个才是调用类的常量。  常量只能用双冒号::来调用。并且不能更改其值。  在类外部实例化后调用类常量同样也有两种方法。方法为:  “$e::PI” 或 “test::PI”,共同点是都要用冒号,不同点是外部不能用this关键字,只能用实例名,但类名::PI是通用的。 
  六、类的静态成员(静态属性或静态方法):  如果需要创建供所有类的实例共享的字段或方法。就得用静态成员。有两个特征:  1、静态成员是********者,它让脚本上的所有该类的实例调用,但不能借助类的特定实例名调用,而是在类的外部,统一使用“类名::$成员名”的方式调用。而类的内部则统一使用 “self::$成员名”来调用。  2、当每一次新创建实例时,静态成员会从上次创建的实例最后值开始重新计算,而不是类中初始的值开始计算。  3、对于用public定义的静态成员,可以在外部更改它的值。private等则不行。  class test{   public static $v = 0;   function __construct(){ self::$v++; }   static function getV(){ return self::$v; }  }  $a = new test();  echo test::getV(); // 返回 1  $b = new test();  echo test::getV(); // 返回 2  test::$v=8; //由于public定义的成员,改变静态成员的值。  $c = new test();  echo test::getV(); // 返回 9 
  七、关键字:  (一)this关键字:用于类的内部指代类的本身。来访问属性或方法或常量,如$this->属性名或方法名。$this::常量名。this还可以用在该类的子类中,来指代本身的属性或方法。  (二)双冒号“::”关键字:用于调用常量、静态成员。  (三)self关键字:在类的内部与双冒号配合调用静态成员,如 self::$staticVar.,在类的内部,不能用$this来调用静态成员。  (四)__toString():在类中使用__toString(),用于将类转成字串并打印类,用处不大:如:  class test{ public $p;   public function __toString(){ return var_export($this,TRUE); }  }  $a=new test();  echo $a; //输出:test::__set_state(array( ’p’ => NULL, )),或写成:echo $a->__toString();  (五)__clone() :当克隆对象时,这个关键字才会发生作用,用于更改克隆时某些值。  (六)__call():方法重载,参下面示例:  class cB{  function __call($method,$n){   if($method==’showVarType’){   if(is_numeric($n[0])){ //不能用$n。要用$n[0];   $this->displayNum();   }else if (is_array($n[0])){   $this->displayArr();   }else{   $this->displayOther();   }   }  }  function displayNum() {   echo ’ 这是数字!’;  }  function displayArr() {   echo ’这是数组!’;  }  function displayOther() {   echo ’不是数组也不是数字!’;  }  } 
  $x=’a’;  $y=array(’a’,’b’);  $b=new cB;  $b->showVarType($x); //不是数组也不是数字  $b->showVarType($y); //这是数组  注意,不能在类中定义showVarType()方法,否则代码不能用。  (七)extends:继承: 如class a{} class b extends a{} 类b继承了类a 
 
  附:记忆:以后统一在调用方法或属性时用 "-> ",调用常量则用双冒号“::”,不会搞晕。 
  八、方法和属性的作用域:  共有6种:public(默认,可省略,也等同于php6的var声明),private(私有,也不能由子类使用),protected(私有,但可由子类使用) ,abstract(抽象,参下文),final(阻止在子类中覆盖—也称重载,阻止被继承,用于修饰类名及方法,如final class test{ final function fun(){}} ,但不能用于属性),static(静态) 
  九:抽象类和抽象方法(abstract——注意:没有所谓抽象属性):  抽象可以理解成父类为子类定义了一个模板或基类。作用域abstract只在父类中声明,但在子类中实现。注意事项:  1、抽象类不能被实例化,只能被子类(具体类)继承后实现。  2、抽象类必须在其子类中实现该抽象类的所有抽象方法。否则会出错。  3、在抽象方法中,只是声明,但不能具体实现:如abstract function gettow(){ return $this->p; }是错的,只能声明这个方法:abstract function gettow();(连方括号{}都不要出现),抽象方法和抽象类主要用于复杂的类层次关系中。该层次关系需要确保每一个子类都包含并重载了某些特定的方法。这也可以通过接口实现  4、属性不能被命名为抽象属性,如abstract $p = 5是错的。  5、只有声明为抽象的类可以声明抽象方法,但如果方法声明为抽象,就不能具体实现。如:  abstract class Employee  {   abstract function a(...);   abstract function b(...);  }  以后再对这个父类扩展,组成各种子类(如经理,员工,出纳)。  6、抽象类中,如果要实现具体的方法,不能声明为抽象。这样可能实际意义更大。可以把几个类库****同的部分提取到抽象类中,其它的类继承抽象类即可。如下:  abstract class BaseShop{   Const TAX=0.06; // 在抽象类中定义常量   public function buy($gid) { // 如果定义为抽象方法abstract function buy()就不能在这里实现主体。   echo(’你购买了ID为 :’.$gid.’的商品’);   }   public function sell($gid) {   echo(’你卖了ID为 :’.$gid.’的商品’);   }   public function view($gid) {   echo(’你查看了ID为 :’.$gid.’的商品’);   }  }  class BallShop extends BaseShop{   var $itme_id = null;   public function __construct()   {   $this->itme_id = 2314;   }   public function open()   {   $this->sell($this->itme_id);   }   public function getTax()   {   echo printf(’平均税率是 %d%%。’,$this::TAX*100);   }  }  $s = new BallShop;  $s->open(); //你卖了ID为 :2314的商品  $shop->getTax(); 
  十:类型提示:  注意,类型提示功能只能用于参数为对象的提示,而无法用于为整数,字串,浮点等类型提示。有些类的方法需要传入的参数为所期望的对象类型,可以用下面的方法达到强制实施此替则。要达到类型提示,只要在方法的对象型参数前加一个已存在的类的名称,如:function funname(OtherClassName $otherclassINSName,$c....),注意,OtherClassName必须是存在的类。如下:  class em{ var $k=56; }  class test{  function __construct()  { echo $this->addab(new em(),2); } 
  function addab(em $j,$c) //这个方法,即可以在内部调用,也可以在外部调用。只要作用域许可。  { return $j->k+$c; }  }  $a = new test();  $b = new em();  echo $a->addab($b,2); //或 $a->addab(new em(),2); 
  十一、类的管理:  1、instanceof关键字:用于分析一个对象是否是某一个类的实例或子类或是实现了某个特定的接口:如下例,但要注意: 类名没有任何引号等定界符,否则会出错。如test不能用’test’  class test2{}  class test{}  class testChilern Extends test{}  $a = new test2();  $m = new test();  $i = ($m instanceof test);  if($i)echo ’$m是类test的实例! ’; // get this value  switch ($a instanceof test){   case true :   echo ’YES ’;   break;   case false :   echo ’No ’; //get this value   break;  }  $d=new testChilern();  if($d instanceof test)echo ’$d是类test的子类! ’; // get this value  2、确定类是否存在:boolean class_exists(string class_name): class_exists(’test’);  3、返回类名:string get_class(object),成功时返回实例的类名,失败则返回FALSE:  $a = new test2(); echo get_class($a); //返回 test2  4、了解类的公用属性:array get_class_vars(’className’) ,返回关键数组:包含所有定义的public属性名及其相应的值。这个函数不能用实例名做变量  5、返回类方法:get_class_methods(’test’); //或: get_class_methods($a);可用实例名做参数,返回包括构造函数在内的所有非私有方法。  6、print_r(get_declared_classes())了解当前PHP版本中所有的类名。PHP5有149个。  7、get_object_vars($a)返回实例中所有公用的属性及其值的关联数组。注意它和get_class_vars()的区别:  /* (1) get_object_vars($a)是用实例名做参数,而get_class_vars(’test’)是用类名做参数。  * (2) get_object_vars($a)获得的属性值是实例运行后的值,而get_class_vars(’test’)获得的属性值是类中的初始定义。  * (3) 两者均返回关联数组,且均对未赋值的属性返回NULL的值。如类test中有定义了public $q;则返回Array ( [v] => 5 [q]=>) ,  */  8、返回父类的名称:get_parent_class($b);//或get_parent_class(’test2’); 返回test  9、确定接口是否存在:boolean interface_exists($string interface[,boolean autoload])  10、确定对象类型: boolean is_a($obj,’className’),当$obj属于CLASSNAME类时,或属于其子类时,返回TRUE,如果$obj与class类型无关则返回FALSE。如:is_a($a,’test’)  11、确定是否是某类的子对象:当$b是继承自TEST类时,返回TRUE,否则FALSE。 
 |