欢迎光临
我们一直在努力

为面向对象而生的PHP5-PHP教程,PHP应用

建站超值云服务器,限时71元/月

摘要]目前开发中的php5,其面向对象的机能已经被大幅度的强化了。下一代的php将会是怎样的一种语言呢?下面我们来详细讲解一下目前发布的php5的beta release。

(一) zend 2.0的诞生

现在的php4所使用的基本文法是被称之为zend 引擎的脚本编译引擎。这个就是php4的优良机能的原因之一,是作为对php3的改进而生成的一种语言。大家一直认为,php4的性能根据当初的目标,比php3有了很大的提升,在网络编程的世界里占据了很大的份额。

开发了zend 引擎的zend公司是在开发php4的同时,由php3的主要开发者zeev suraski和andi gutmans所创立的企业合并而来的。zend的名称是由zeev和andi的名字合起来组成的。zend公司的商业模式是,持续不断的为open source提供zend 引擎的php内核 (core),同时提升周边产品开发和贩卖的利益。以open source software作为基盘的商业,在世界范围内大多数正在苦战的企业中,算是比较好的典型例子了。

■php4的局限

托php4成功的福,这个用途的适用范围逐渐变广起来。作为企业级的用途而使用php的说法时有所闻。因此,就有了这样一个问题,构筑大规模网站的时候,代码的再利用性十分差。具体来说就是,php4的面向对象性能很弱,因此习惯于使用java等的技术人员对此有很多的抱怨。

逐步的改善php4的面向对象的性能,大幅度的更改基本文法,开发者达成了更新php记述方法的开拓目的。

■zend 2.0开始开发

随后,zend公司php中心的开发者们在2001年7月发表了作为下一代php语言引擎的zend 2.0引擎的构想。以[zend engine version 2.0: feature overview and design]

(http://www.zend.com/engine2/zendengine-2.0.pdf)作为目标的同时,面向对象的性能大幅度的强化了。

目前的php4 zend 引擎的扩张情况与昔日的php3如出一辙。这就意味着,要提升新的语言引擎的主版本号,明确方法目标,迎接来自开发团体的称赞。

ze2的开发,与以往的zend引擎一样,都是运行在open source的模式下的。最新的源代码在cvs上被全面的公开,因为是面向开放的开发者的,关于开发的议论非常的活跃。

现在ze2被决定采用于php的下一个版本php5中。最终发布的时间现在还未定,但是假如根据zend公司2003年4月1日发布的newsletter的话,现在的应该就是beta release了。

(二) php5的新特性

接下来请按照顺序看一下被强化的php5的性能。首先是最为重要的面向对象性能,类的实体特性在大幅度的被修改着。这里说的仅是关于类的新特性。

· 对象的参照过渡是默认的(default)

· 引入访问属性的限制

· 引入访问方法的限制

· 抽象类和抽象方法

· 接口

· final声明

· 名空间

· 类内常量

· 类变量

· 统一构建器

· 析构函数(distructor)

· 其他附属特性

以上内容是根据2003年4月22日cvs上登录版本资料所写的,在正式的发布之前,也有变动的可能性。

■对象的默认参照过渡

在php4中,在以变量$var1为类的实体对象的时候,如果$var2 = $var1;那么,在$var2中,$var1的复制被代入。明显的,$var2为了指向与$var1相同的对象,就要写成$var2 =& $var1,必须要加上&作为参照。

而在php5,对象的代入将成为自动的参照过渡。也就是说,

$var2=$var1,两者指向相同的对象。如果想要同php4一样,带入copy,那么就会运用到导入__clone()的方法。

$var2 = $var1->__clone();此处,clone前面是两个连续的“_”

(这仅仅是类的实体的特性)

■引入访问属性的限制

在php4的类中,连同属性和方法在内,可以自由的访问类的内外任何地方,而没有限制。因此,用户就无法防范属性的无意中的更改。

而在php5中,同c++和java一样,导入了private, protected, public三个等级的访问限制,使得类的设计者能够对属性和方法的使用方法进行限定。以下是各种访问限制的意思。

· public: 可以自由的在类的内外任何地方进行参照、变更

· private: 只能在这个类的方法中进行参照、变更

· protected:能够在这个类以及继承了这个类的另一个类的方法中进行参照、变更。另外,在继承的类中,能够写入访问指定。

在php4中的“var”,同以往一样与public有着相同的意思。下面就来举一个例子,让我们来看看访问限制是怎样起作用的。

php代码:——————————————————————————–

class hoge1 {

 private $var1 = a;

 protected $var2 = b;

 protected $var3 = c;

 function setlower() {

  $this->var1 = a;

  $this->var2 = b;

  $this->var3 = c;

 }

 function var1() {

  return $this->var1;

 }

 function var2() {

  return $this->var2;

 }

 function var3() {

  return $this->var3;

 }

}

——————————————————————————–

在这个类中,带有$var1, $var2, $var3三个属性。$var1被声明为private, $var2和$var3是protected.在此处

php代码:——————————————————————————–

$hoge=new hoge1;

echo’var1:’.$hoge->var1.”

n”

——————————————————————————–

如果尝试参照不允许从外部进行访问的private属性,那么就会出现如下错误:

fatal error: cannot access private property hoge1::$var1 in /path/to/script.php on line xx

对于protected的$var2也是相同的。

但是,因为$hoge的方法是没有private和protected的,所以下面的代码能够正常运作,返回内部私有和保护变量的值。

php代码:——————————————————————————–

echo var1: . $hoge->var1() . "

\n"; // var1: a

echo var2: . $hoge->var2() . "

\n"; // var2: b

echo var3: . $hoge->var3() . "

\n"; // var3: c

$hoge->setlower();

echo var1: . $hoge->var1() . "

\n"; // var1: a

echo var2: . $hoge->var2() . "

\n"; // var2: b

echo var3: . $hoge->var3() . "

\n"; // var3: c

——————————————————————————–

其次,为了能够看到protected的属性的状态,我们试着创造了继承了hoge1的类hoge2

php代码:——————————————————————————–

class hoge2 extends hoge1 {

 public $var3 = 3;

 function d_var1() {

  return $this->var1;

 }

 function d_var2() {

  return $this->var2;

 }

 function d_var3() {

  return $this->var3;

 }

}

——————————————————————————–

在类hoge2中,只有$var3被声明为public。在属性是protected的情况下,从子类进行访问有何种限制,是由子类的属性声明决定的。在hoge2中,因为$var3被声明是public,因此无论是从何处都可以访问hoge2的$var3(实体是hoge1的$var3)。因为$var1在hoge1中是private,因此,在hoge2子类中hoge1的$var1不会被继承,而在hoge2中有可能会做出名为$var1的属性,因此,必须要明确区分hoge1::$var1和hoge2::$var1。

php代码:——————————————————————————–

$hoge = new hoge2;

echo var1: . $hoge->var1 . "

\n";   // var1:

// echo var2: . $hoge->var2 . "

\n";  // error

echo var3: . $hoge->var3 . "

\n";   // var3: 3

echo var1: . $hoge->d_var1() . "

\n"; // var1:

echo var2: . $hoge->d_var2() . "

\n"; // var2: b

echo var3: . $hoge->d_var3() . "

\n"; // var3: 3

——————————————————————————–

$hoge->var1是与hoge1::var1没有关系的变量,因此不会有任何显示,因为var2有protected访问限制,所以如果不通过method就直接参照$var2,就会出现致命错误。

■引入访问方法的限制

与上述相同,此处也分为private, protected, public三种。

· public: 能够从任何地方调用

· private: 只能够从这个类的method内调用

· protected: 只能够从这个类以及subclass的method中调用

此处的意思同java和c++相同,请不要搞混。

■抽象(abstract)的类和抽象的方法

支持与java相同的抽象类和抽象方法。抽象方法只提供了方法名的调用方式,而没有提供实体。另外,持有抽象方法的类,必须抽象宣言类本身。如果想要直接作成抽象类的对象,那么就会出现如下的致命错误。

fatal error: cannot instantiate abstract class classname

产生错误的实际的例子如下所示:

php代码:——————————————————————————–

abstract class myabstract {

 abstract public function test();

 public function test2() {

  echo "myabstract::test2() called.

\n";

 }

}

class myimplement extends myabstract {

 public function test() {

  echo "myimplement::test() called.

\n";

 }

}

$obj = new myimplement;

$obj->test();

?>

——————————————————————————–

■接口(interface)

支持与java相同的接口(interface)。接口是适合所描述的外部调用形式而设计组合起来的。

接口的实体不能够记录。相反的,实现接口的类必须持有与这个接口的方法相对应的实体。另外,类能够实现多个接口,因此,有可能实现多重继承。

php代码:——————————————————————————–

interface throwable {

 public function getmessage();

}

interface serializable {

 public function tostring();

}

class myexception implements throwable, serializable {

 public function getmessage() {

  return this is myexception message;

 }

 public function tostring() {

  return myexception: this is myexception message;

 }

}

$e = new myexception;

echo $e->getmessage();

echo $e->tostring();

?>

——————————————————————————–

■final声明

同java一样,php5支持final声明。如果对于一个方法追加final声明,这个方法将肯定在子类不能重载(override)。如果方法被final声明了,但是还在子类中重载,就会出现如下错误:

php代码:——————————————————————————–

fatal error: cannot override final method fuga::foo()

——————————————————————————–

产生错误的例子:

php代码:——————————————————————————–

class fuga {

 final function foo() {

  echo "this is final function\n";

 }

}

class hoge extends fuga {

 function foo() {

  echo "this is not final function\n";

 }

}

?>

——————————————————————————–

(三) php5的新特性(续)

php5的发布计划

在前面的文章中我们提到,“根据zend公司2003年4月1日发布的讯息的话,现在的应该就是beta release了”,但是开发者内部讨论的结果是,beta为时尚早,而且有可能不是beta release.

对这方面动向有兴趣的可以参照 news://news.php.net/ 上所公布的信息 php.version5.dev:372

在这个文件中,php5的发布计划又重新回到了一张白纸,而另一方面,zend engine2的开发正在着手进行中。php5的release其实大体就是盼望着“快点到年终吧”。

php5的新特性

接着我们来看一下在前面所讲到的其他一些关于类的新增的机能

■名空间

php5支持名空间。因此,我们可以在名空间内装入类、变量、常量、函数。

在php4的scope中,只有global、函数内、类内这三个种类,所以要特别注意如果不注意的话,将会很容易“污染”global空间。假如使用名空间的话我们就能够在package里分离变量命名空间,因此应该就能比较容易的做成独立的package。

使用实例如下:

php代码:——————————————————————————–

namespace this {

 class hoge {

 }

 const aconstant = this constant;

 function afunction() {}

 var $avariable = this variable;

}

$obj = new this::hoge;

echo this::aconstant . "

\n";

this::afunction();

echo this::$avariable . "

\n";

——————————————————————————–

假设要访问名空间内的对象的话,就应该这样做:

名空间名::对象名

但是php5的名空间不会套入与c++相异的样子。

■class内常量

使用关键字const,能够在类、名空间内定义常量。这里因为是常量,因此一定要在常量名的前面加上$。class内的常量,比这个类中的global常量的优先级要高。

在这里const是预约语,因此在class名和函数名中使用const的时候要做必要的修正。

php代码:——————————————————————————–

define(constant_value, global constant);

class myclass {

 const constant_value = class constant;

 function printconstant() {

  print constant_value;

 }

}

echo myclass::constant_value . "

\n";

myclass:rintconstant();

?>

——————————————————————————–

在这个例子里,myclass:rintconstant()是显示常量constant_value的值,但是,constant_value存在于global空间和class内这两个地方。在这种情况下,myclass内的常量constant_value的优先级较高,被显示为「class constant」。

■对象变量

即使是在类没有被实例化状态下,对象变量也能准确的按照指定的值被初始化。访问的方法如下:

类名::$变量名

php代码:——————————————————————————–

class hoge {

 static $my_static = 5;

}

print hoge::$my_static;

?>

——————————————————————————–

■统一构建器

在生成对象的时候,能够自动被调用的方法被称作“构建器”。

php4中的构建器,是与class名相同的方法名。这是与java和c++相同的地方,因此,对于一些用惯了的人来说,不会有别扭感。但是,如果要从子类中调用父类的构建器的话,在php中就必须特意写上父类的名字。

在php中,父类的构建器不能被自动调用,因此,情况就比较多。

在php5中,统一采用了__constructor这个构建器名称,不管class名是什么,凡是被称为__construct()的,都被当作构建器来处理。

另外,考虑到同php4的互换性,假如存在于class名相同的以前的构建器名,那么,优先使用那个构建器。

php代码:——————————————————————————–

class baseclass {

 function __construct() {

  print "in baseclass constructor\n";

 }

}

class subclass extends baseclass {

 function __construct() {

  parent::__construct();

  print "in subclass constructor\n";

 }

}

$obj = new baseclass();

$obj = new subclass();

?>

——————————————————————————–

■析构函数

与构建器相反,能够在对象释放时自动被调用的方法被称为析构函数。

php4支持析构函数,通过登录在php运行终止时用register_shutdown_function()调用的函数,只有类似的实行方法。php5正式支持析构函数,能够在类中指定对象释放时的动作。

析构函数就是名为__destruct的方法。当对象内部的参照计数器变成0的时候,__destruct()被调用,然后对象所使用的内存被释放出来。

php代码:——————————————————————————–

class mydestructableclass {

 function __construct() {

  print "in constructor\n";

  $this->name = mydestructableclass;

 }

 function __destruct() {

  print destroying . $this->name . "\n";

 }

}

$obj = new mydestructableclass();

?>

——————————————————————————–

另外,与构建器相同的地方是,父类的析构函数不能被自动的调用,必要的时候,需要用命令:

parent::__destruct();

■访问

在php4中,如果访问了一个不存在的属性,那么系统就会自动生成与之相对应的新属性。

php代码:——————————————————————————–

class hoge {

}

$obj = new hoge;

$obj->prop = "this is new property";

——————————————————————————–

如上所示,当把值代入一个不存在的属性时,那个代入点就会自动生成一个新属性。同样的,访问一个不存在的属性,就如同被代入null值的变量一样,不会发生错误。

在php5中追加了一点,就是能够对访问任意的属性进行控制。在类中如果存在__set()、__get()这样的方法,替代上述的动作此处的方法将能够被调用。例如:

php代码:——————————————————————————–

class hoge {

 function __set($name, $value) {

  print "__set() is called with ($name, $value)\n";

  $this->$name = $value;

 }

}

$obj = new hoge;

$obj->a = 123;

$obj->a = 456;

$obj->b = 789;

?>

——————————————————————————–

在这里,__set 方法被作为未定义属性的代入方法,在显示值之后将值代入未定义属性。

php代码:——————————————————————————–

$obj->a = 123;

——————————————————————————–

执行这一句时,因为在这个时候不存在属性a,因此,作为代替,__set 方法被调用。

__set() is called with (a, 123)

其次,

$obj->a = 456;

再一次的代入$obj->a,这一次,由于属性a已经存在,所以__set 没有被调用,和通常一样把值代入到了属性a中去了。

$obj->b = 789;

这一回,我们把值代入另一个属性b中,同a的第一次情况一样,

__set() is called with (b, 789)

同__set 方法相反,__get 方法是在对不存在的属性的引用时调用的。将这两者结合起来,再来看一下对于属性的访问,实际上,利用它能够写出在不同的场合都能做出不同响应的类来。

php代码:——————————————————————————–

class hoge {

 public $properties;

 function __set($name, $value) {

  $this->properties[$name] = $value;

 }

 function __get($name) {

  return $this->properties[$name];

 }

}

$obj = new hoge;

$obj->a = 123;

$obj->b = 456;

echo $obj->a;

echo $obj->b;

print_r($obj);

?>

——————————————————————————–

在这个例子里,对类中所有属性的访问被装入了$properties中,这样,使我们加入的属性不直接的附在对象之下。这是个不太能容易理解的例子,例如,试着把这个例子中的保存到$properties改成存入文件或是数据库会很有趣吧。实际上,在对象里面,我们能够简单的实现让许多的复杂的操作。

与__set, __get多少有些不同,但是__call也能用来书写不存在的方法,当我们向如下例子一样调用对象的方法的时候,

$object->methodname();

如果这个类中不存在methodname这个方法,通常情况下,就会出现如下错误:

fatal error: call to undefined method class::methodname()

但是,如果这个类中存在__call这个方法,作为替代,__call就被调用。__call的参数有两个,第一个参数是被叫出的方法名,第二个参数是保持了的被调用的参数的数组。考虑到有很多的使用方法,除了以下的例子外,还可以使用其它的方法。

php代码:——————————————————————————–

class proxy {

 private $object;

 function __call($name, $params) {

  if (isset($this->object)) {

   if (method_exists($this->object, $name)) {

   return call_user_func_array(array($this->object, $name), $params);

   }

   else {

   return "method not exists.";

   }

  }

 }

 function __construct($object) {

  $this->object = $object;

 }

}

class hoge {

 function add($var1, $var2) {

  return $var1 + $var2;

 }

}

$p = new proxy(new hoge);

$result = $p->add(1, 2);

echo "result: $result

\n";

$result = $p->sub(5, 3);

echo "result: $result

\n";

?>

赞(0)
版权申明:本站文章部分自网络,如有侵权,请联系:west999com@outlook.com 特别注意:本站所有转载文章言论不代表本站观点! 本站所提供的图片等素材,版权归原作者所有,如需使用,请与原作者联系。未经允许不得转载:IDC资讯中心 » 为面向对象而生的PHP5-PHP教程,PHP应用
分享到: 更多 (0)