第1次亲密接触PHP5(1)

  文章来源:PHPBuilder.com

  原作者:Luis Argerich

  翻译:erquan

  erquan注:本人现还未来得及体验PHP5,只是翻译一篇老外的文章。

  以下均由erquan翻译,第1次作这些的事情希望没有误导大家。有些不准的地方请谅解。

  大家看这样的行不行,如果行的话,偶就翻译完,不行就翻译了,免得误导了大家,也累哦。。。。:)

  转贴时请注明文章来源,谢谢:)

  PHP5的正式版还没发布,但我们可以学习、体验下开发版给我们带来的PHP新特性。

  本文将集中介绍以下3大PHP5新功能:

  * 新对象模式

  * 结构化异常处理

  * 名称空间

  在正式开始之前,请注意:

  *文章中的部分例子用PHP4的方法实现,只是为了增强文章的可读性

  *本文所描述的新特性可能会与正式版特性有出入,请以正式版本为准。

  * 新对象模式

  PHP5新的对象模式在PHP4的基础上做了很大的"升级",你看起来会很像JAVA:(。

  下面的一些文字将对它做一些简单介绍,并且附有小例子让您开始体验PHP5的新特性

  come on~~:)

  * 构造函数 和 析构函数

  * 对象的引用

  * 克隆对象

  * 对象的3种模式:私有、公共和受保护

  * 接口

  * 虚拟类

  * __call()

  * __set()和__get()

  * 静态成员

  构造函数 和 析构函数

  在PHP4中,和类名一样的函数被默认为该类的构造器,并且在PHP4没有析构函数的概念。(二泉 注:这点和JAVA一样)

  但从PHP5开始,构造函数被统一命名为 __construct,而且有了析构函数:__destruct(二泉 注:这点却和Delphi一样,可见PHP5吸收了众多的成熟的OO思想,可C可贺~~):

  例1:构造函数和析构函数

  <?php

  class foo {

  var $x;

  function __construct($x) {

  $this->x = $x;

  }

  function display() {

  print($this->x);

  }

  function __destruct() {

  print("bye bye");

  }

  }

  $o1 = new foo(4);

  $o1->display();

  ?>

  运行完你将看到输出了"bye bye",这是因为类在终止的时候调用了__destruct()析构函数~~

  对象的引用

  正如你所知道的一样,在PHP4中,对一个函数或方法传递一个变量时,实际上是传递了一个copy,除非你用了传址符&来声明

  你在做一个变量的引用。在PHP5中,对象总是以引用的方式被指定:

  例2:对象的引用

  <?php

  class foo {

  var $x;

  function setX($x) {

  $this->x = $x;

  }

  function getX() {

  return $this->x;

  }

  }

  $o1 = new foo;

  $o1->setX(4);

  $o2 = $o1;

  $o1->setX(5);

  if($o1->getX() == $o2->getX()) print("Oh my god!");

  ?>

  (二泉 注:你将看到"Oh my god!"的输出)

  克隆对象

  如上,如果有时不想得到对象的引用而想用copy时,怎么办?在PHP5提供的 __clone 方法中实现:

  例3:克隆对象

  <?php

  class foo {

  var $x;

  function setX($x) {

  $this->x = $x;

  }

  function getX() {

  return $this->x;

  }

  }

  $o1 = new foo;

  $o1->setX(4);

  $o2 = $o1->__clone();

  $o1->setX(5);

  if($o1->getX() != $o2->getX()) print("Copies are independant");

  ?>

  克隆对象的方法在已被应用到很多语言中,所以你不必担心它的性能:)。

  Private, Public 和 Protected

  在PHP4中,你可以在对象的外面操作它任意的方法和变量--因为方法和变量是公用的。在PHP5引用了3种模式来控制

  对变量、方法的控制权限:Public(公用的)、Protected(受保护)和Private(私有)

  Public:方法和变量可以在任意的时候被访问到

  Private:只能在类的内部被访问,子类也不能访问

  Protected:只能在类的内部、子类中被访问

  例子4:Public, protected and private

  <?php

  class foo {

  private $x;

  public function public_foo() {

  print("I'm public");

  }

  protected function protected_foo() {

  $this->private_foo(); //Ok because we are in the same class we can call private methods

  print("I'm protected");

  }

  private function private_foo() {

  $this->x = 3;

  print("I'm private");

  }

  }

  class foo2 extends foo {

  public function display() {

  $this->protected_foo();

  $this->public_foo();

  // $this->private_foo();  // Invalid! the function is private in the base class

  }

  }

  $x = new foo();

  $x->public_foo();

  //$x->protected_foo();  //Invalid cannot call protected methods outside the class and derived classes

  //$x->private_foo();    //Invalid private methods can only be used inside the class

  $x2 = new foo2();

  $x2->display();

  ?>

  提示:变量总是私有形式,直接访问一个私有变量并不是一个好的OOP思想,应该用其他的方法来实现 set/get 的功能

  接口

  正如你知道的一样,在 PHP4 中实现继承的语法是"class foo extends parent"。无论在PHP4 还是在 PHP5 中,都不支持多重继承即只能从一个类往下继承。 PHP5中的"接口"是这样的一种特殊的类:它并不具体实现某个方法,只是用来定义方法的名称和拥有的元素,然后通过关键字将它们一起引用并实现具体的动作。

  Example 5: 接口

  <?php

  interface displayable {

  function display();

  }

  interface printable {

  function doprint();

  }

  class foo implements displayable,printable {

  function display() {

  // code

  }

  function doprint() {

  // code

  }

  }

  ?>

  这对代码的阅读性和理解性是非常有帮助的:读到该类时,你就知道foo包含了接口displayable和printable,而且一定有print()(二泉 注:应该是doprint())方法和display()方法。不必知道它们内部是如何实现就可轻松操作它们只要你看到foo的声明。

  虚拟类

  虚拟类是一种不能被实例化的类,它可以像超类一样,可以定义方法和变量。

  在虚拟类中还可以定义虚拟的方法,而且在该方法也不能在该类是被实现,但必须在其子类中被实现

  Example 6: 虚拟类

  <?php

  abstract class foo {

  protected $x;

  abstract function display();

  function setX($x) {

  $this->x = $x;

  }

  }

  class foo2 extends foo {

  function display() {

  // Code

  }

  }

  ?>

  __call()方法

  在PHP5时,如果你定义了 __call()方法,当你试图访问类中一个不存在的变量或方法时,__call()就会被自动调用:

  Example 7: __call

  <?php

  class foo {

  function __call($name,$arguments) {

  print("Did you call me? I'm $name!");

  }

  }

  $x = new foo();

  $x->doStuff();

  $x->fancy_stuff();

  ?>

  这个特殊的方法被习惯用来实现"方法重载",因为你依靠一个私有参数来实现并检查这个参数:

  Exampe 8:  __call 实现方法重载

  <?php

  class Magic {

  function __call($name,$arguments) {

  if($name=='foo') {

  if(is_int($arguments[0])) $this->foo_for_int($arguments[0]);

  if(is_string($arguments[0])) $this->foo_for_string($arguments[0]);

  }

  }

  private function foo_for_int($x) {

  print("oh an int!");

  }

  private function foo_for_string($x) {

  print("oh a string!");

  }

  }

  $x = new Magic();

  $x->foo(3);

  $x->foo("3");

  ?>

  __set()方法 和 __get()方法

  当访问或设置一个未定义的变量时,这两个方法将被调用:

  Example 9: __set and __get

  <?php

  class foo {

  function __set($name,$val) {

  print("Hello, you tried to put $val in $name");

  }

  function __get($name) {

  print("Hey you asked for $name");

  }

  }

  $x = new foo();

  $x->bar = 3;

  print($x->winky_winky);

  ?>