chengren-成人-php系列4

2010年最新PHP类的精缩归纳

chengren-成人-php系列4

 

类的家族化扩展:

类的高级功能:

一、对象克隆:

当克隆一个对象的实例时,其属性初始值继承了被克隆对象的当前值。

class test
{
public $p=5;
function __clone(){ //只在克隆发生时起作用。用于改变在克隆时某些值
$this->p=15;
}
}
$a=new test();
echo $a->p;
$a->p=8; //如果没有__clone()方法影响,$b的P值将为8
$b = clone $a;
echo $b->p; //15

二、对象继承:

没有被声明为final的类可以被继承,没有被final和private界定的方法也可以继承,没有被private界定的属性也可以继承。当子类继承了父类或超类后,可以直接使用父类或超类(祖父类以及祖父的祖父)的所有允许的方法,属性。

关键:理解构造函数和重载在继承中的特性!

(一)构造函数在继承中的特性:

1、当父类有构造函数而子类没有:则子类会在实例化时会自动执行父类的构造函数。这时如果要创建子类的实例,需要引入父类构造函数中所需的参数,否则出错。即使是“子类的子类”如果没有构造函数,也要在创建实例时输入其父类的父类的构造函数所需参数。PHP会从实例所在的子类会向上搜索合造的构造函数,一旦找到就停止,使用该构造函数。而不会再向上搜索,因此:子类本身如果没有构造函数,则以其最靠近的一个超类并且有构造函数的为准。

class cA{
public $name,$age;
function __construct($n) {
$this->name = $n;
$this->age = 25;
}
function __set($n,$v) {
$this->$n = $v;
}
function __get($n) {
return $this->$n;
}
}

class cB extends cA{
function funB1() { echo '<h3>Class cB execute success!</h3>'; }
}

class cC extends cB {
function funC1() { echo '<h3>Class cC FunC1!</h3>'; }
}
$b=new cB('Jack');
$b->name='John';
echo "$b->name : $b->age";
$b->funB1();
$c=new cC(); //这里会出错,由于cB也没有构造函数,因此再向上以cA为准,需要一个参数。改为$c=new cC('David');即可。
echo $c->name(); //David

2、当子类也有构造函数时:这时,不管父类是否有构造函数,都会执行子类自己的构造函数。

如上:

class cB extends cA{
function __construct() {
echo '<h3>this is Class cB \'s __construct!</h3>';
}
function funB1() {
echo '<h3>Class cB execute success!</h3>';
}
}

现在类CB有自己的构造函数时,这时创建实例$b=new cB('Jack');参数JACK不会起作用,因为父类CA的构造函数没有得到执行。因此$b->name和$->age就不会初始化值。需要另外赋值$b->name='Jack',$b->age=25;

如果这时要执行父类CA的构造函数,可以这样:

function __construct($n) {
parent::__construct($n); // 或:cA::__construct($n);
echo '<h3>this is Class cB \'s __construct!</h3>';
}

由于parent::__construct($n); 只会向上搜索父类的构造函数,一找到就停止且执行当前找到的构造函数,因此在上面例子中,如果parent::__construct($n)是用在最后一层的类cC中,并且类CB,CA都有构造函数,那么cC的实例只会执行cB的构造函数。不会执行cA。这时,如果CC的实例想都调用CA和CB的构造函数,有两种方法:

A、在CB中也加入parent::__construct($n)

B、在CC中把构造函数改为:

function __construct($n) {
cA::__construct($n); //即:类名::构造函数。
cB::__construct();
echo '<h3>this is Class cB \'s __construct!</h3>';
}

(二)在子类中调用父类的属性或方法:

1、调用父类方法:在子类中调用父类的方法,有3种方法:

$this->ParentFunction(); 或

父类名::ParentFunction(); 或

parent::parentFun();

2、调用父类属性:只能用$this->ParentProperty;

(三)重载:

在子类中,可以定义与父类相同属性或方法,改变父类该属性或方法的值或操作,称做重载。如:

calss ParClass{ function pfun(){ ....}}

class ChildrenClass extends ParClass{function pfun(){ ....}}} //重载了父类的pfun的方法。

在子类中重载后,优先执行自己重载后的新定义的方法或属性。

也可以在子类中用parent::parentFun();调用父类的方法,但所得到的值是子类自己输入的参数运算值。而不是该方法在父类中运算的值。

三、接口:

接口:interface,可以理解成一组功能的共同规范,最大意义可能就是在多人协作时,为各自的开发规定一个共同的方法名称。

和抽象类中的抽象方法一样:

1、不能在接口中对方法具体实现进行定义。而是由具体类来实现(而抽象类中的非抽象方法可以不必再定义,只有抽象方法和接口是一样要求要在具体类中实现)。

2、和抽象类一样,可以在接口中定义常量,并由具体类直接继承。

3、具体类必须实现抽象类的所有抽象方法(非抽象方法除外),同样,具体类如通过implements实现了接口后,必须完成接口中的所有方法。

接口实现过程:1、定义接口,2、用..implement X,Y,...和具体类对接。

interface Info{ //定义接口
const N=22;
public function getage();
public function getname();
}

class age implements Info //如要多个接口 class age (extends emJob) implements Info,interB...
{
public $age=15;
public $name='Join';
function getage() {
echo "年级是$this->age";
}
function getname() {
echo "姓名是$this->name";
}
function getN(){
echo '<h3>在接口中定义的常量N的值是:'.$this::N.' </h3>'; //直接继承接口中的常量值。
}
}

$age=new age;
echo $age::N; //22,直接调用接口中的常量值。
$age->getN();

关于抽象类和接口类的使用区分:何时用接口,何时用抽象?

1、相关性:当创建的模型由一些紧密相关的对象采用时,用抽象。对于不相关对象采用的功能,用接口。

2、多重继承:PHP类可以继承多个接口,但不能扩展多个抽象类。

3、公共行为实现:抽象类可在其中实现公共的方法,但接口不行。

四、命名空间(PHP6)

类库脚本A.inc.php和脚本B.inc.php中都一个类的名称为 class CNAME,并且这两个文件要在同一个文件如index.php中被调用。这时要用到命名空间。

步聚:

1、打开上面的A和B两个文件,分别在上面的最前面各加一行:

namespace SPACEA;   和 namespace SPACEB;   名字自定。

2、在index.php中实例化类时,在类的前面添加命名空间和双冒号做为前缀:

include 'a.inc.php';
include 'b.inc.php';
$a=new SPACEA::CNAME();
$b=new SPACEB::CNAME();

这样就不会冲突了。

但在PHP6正式发布前,这个功能还未定下来。

五、实现迭代器和迭代。

参《PHP圣经》P142;

六、使用Reflection(反射)API 。

简易实例:

class a{ .... }
$c = new ReflectionClass('a'); //PHP 内置类。
echo '<pre>'.$c.'</pre>';

输出类a的结构和内容。参《PHP圣经》P145;

posted on 2010-03-30 11:03  chengren成人  阅读(761)  评论(0编辑  收藏  举报