PHP面试总结(1)php5.0的新特性

前不久,参加某外资公司PHPer岗位面试,笔试面试都英语,这都不是主要的,面试官的几个问题比较有代表性,故作此记录。

面试官问题:请简要说下php5.0的新特性

     做过php开发的同学,特别是经验只有2到3年的,一开始接触php可能都是直接从php5开始的,并没有了解php之前的版本,了解的也不是很多。但是你的面试官可能都35岁了,他们肯定经历过php4的年代,故会有这一问。

  下面总结一下php5.0的新特性:

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

 

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

· 引入访问属性的限制

· 引入访问方法的限制

· 抽象类和抽象方法

· 接口

· final声明

· 名空间

· 类内常量

· 类变量

· 统一构建器

· 析构函数(Distructor)

· 其他附属特性

 

■对象的默认参照过渡

 

在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支持名空间。因此,我们可以在名空间内装入类、变量、常量、函数

在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";

?>

--------------------------------------------------------------------------------

全新的对象模型

PHP中的对象处理部分已完全重写,具有更佳的性能和更多的功能。在PHP的以前版本中,对象与内建变量类型(如integer和string)的处理方 法相同,其弊端是当变量被赋值为对象或对象作为参数传递时,得到的是对象复制品。而在新版本中,对象通过句柄进行引用,而不是通过它的值。(句柄可以认是 为是对象的标识符)

很多PHP程序员可能未意识到以前的对象模型的“复制怪癖”,因此以前的PHP程序将不需要做任何更改,或只做很小的改动即可运行

私有和保护成员

PHP 5引入了私有和保护成员变量,它们可以定义类属性在何时可以被访问。

类的保护成员变量能在该类的扩展类中被访问,而私有成员变量只能在本类中被访问。

class MyClass {

private $Hello = "Hello, World!\n";

protected $Bar = "Hello, Foo!\n";

protected $Foo = "Hello, Bar!\n";

 

function printHello() {

print "MyClass::printHello() " . $this->Hello;

print "MyClass::printHello() " . $this->Bar;

print "MyClass::printHello() " . $this->Foo;

}

}

 

class MyClass2 extends MyClass {

protected $Foo;

 

function printHello() {

MyClass::printHello(); /* Should print */

print "MyClass2::printHello() " . $this->Hello; /* Shouldnt print out anything */

print "MyClass2::printHello() " . $this->Bar; /* Shouldnt print (not declared)*/

print "MyClass2::printHello() " . $this->Foo; /* Should print */

}

}

 

$obj = new MyClass();

print $obj->Hello; /* Shouldnt print out anything */

print $obj->Bar; /* Shouldnt print out anything */

print $obj->Foo; /* Shouldnt print out anything */

$obj->printHello(); /* Should print */

 

$obj = new MyClass2();

print $obj->Hello; /* Shouldnt print out anything */

print $obj->Bar; /* Shouldnt print out anything */

print $obj->Foo; /* Shouldnt print out anything */

$obj->printHello();

?>

---------------------------------------------------------------------------------

私有和保护方法

在PHP 5(ZEND引擎2)中,还引入了私有和保护方法。

例:

class Foo {

private function aPrivateMethod() {

echo "Foo::aPrivateMethod() called.\n";

}

 

protected function aProtectedMethod() {

echo "Foo::aProtectedMethod() called.\n";

$this->aPrivateMethod();

}

}

 

class Bar extends Foo {

public function aPublicMethod() {

echo "Bar::aPublicMethod() called.\n";

$this->aProtectedMethod();

}

}

 

$o = new Bar;

$o->aPublicMethod();

?>

以前代码中的用户自定义类或方法中虽未定义"public," "protected" 或 "private"等关键字,但无需编辑即可运行。

抽象类和方法

PHP 5还引入了抽象类和方法。抽象方法只声明方法定义, 不供实际运行。包含抽象方法的类需要声明为抽象类

例:

abstract class AbstractClass {

abstract public function test();

}

 

class ImplementedClass extends AbstractClass {

public function test() {

echo "ImplementedClass::test() called.\n";

}

}

 

$o = new ImplementedClass;

$o->test();

?>

抽象类不能实例化。以前代码中的用户自定义类或方法中虽未定义"abstract”关键字,但无需编辑即可运行。

接口

ZEND引擎2.0引入了接口。一个类可以运行任意的接口列表。

Example

例:

interface Throwable {

public function getMessage();

}

 

class Exception implements Throwable {

public function getMessage() {

// ...

}

?>

以前代码中的用户自定义类或方法中虽未定义"interface”关键字,但无需编辑即可运行。

类类型定义

在保留类无需定义类型的同时,PHP 5引入了类类型定义来声明希望把哪个类通过参数传递给一个方法。

Example

例:

interface Foo {

function a(Foo $foo);

}

 

interface Bar {

function b(Bar $bar);

}

 

class FooBar implements Foo, Bar {

function a(Foo $foo) {

// ...

}

 

function b(Bar $bar) {

// ...

}

}

 

$a = new FooBar;

$b = new FooBar;

 

$a->a($b);

$a->b($b);

?>

这些类类型定义在不象一些需要类型预定义的语言在编译中进行检查,而是在运行时进行。这意味着:

function foo(ClassName $object) {

// ...

}

?>

等价于:

function foo($object) {

if (!($object instanceof ClassName)) {

die("Argument 1 must be an instance of ClassName");

}

}

?>

本语法只用于对象或类,不适用于内建类型。

---------------------------------------------------------------------------------

final

PHP 5引入了“final”关键字定义在子类中不能被覆盖的成员或方法。

例:

class Foo {

final function bar() {

// ...

}

}

?>

以前代码中的用户自定义类或方法中虽未定义"final"关键字,但无需编辑即可运行。

对象克隆

PHP 4在对象被复制时,用户不能决定拷贝的机制。在复制时,PHP 4只一位一位地复制一个和原来对象一模一样的复制品。

我们并不是每次都要建立一个完全一样的复制品。一个很好的需要一种复制机制的例子是,当有一个代表一个GTK窗口的对象,它拥有该窗口的所有资源,当你建 立一个拷贝时,你可能需要一个新的窗口,它拥有原窗口的所有属性,但需要拥有新窗口的资源。另外一个例子是你有一个对象引用了另外一个对象,当你复制父对 象时,你希望建立那个引用对象的新实例,以使复制品引用它。

对一个对象的拷贝通过调用对象的__clone()方法完成:

$copy_of_object = $object->__clone();

?>

当开发者请求建立一个对象的新的拷贝时,ZEND引擎会检查是否定义了__clone()方法。如果未定义的话,它会调用一个默认的__clone()方 法来复制该对象的所有属性。如果定义了该方法,该方法会负责在拷贝中设置必要的属性。为方便起见,引擎会提供一个函数从源对象中导入所有的属性,这样它就 可以先得到一个具有值的源对象拷贝,只需要对需要改变的属性进行覆盖即可。

例:

class MyCloneable {

static $id = 0;

function MyCloneable() {

$this->id = self::$id++;

}

 

function __clone() {

$this->name = $that->name;

$this->address = "New York";

$this->id = self::$id++;

}

}

 

$obj = new MyCloneable();

 

$obj->name = "Hello";

$obj->address = "Tel-Aviv";

 

print $obj->id . "\n";

 

$obj = $obj->__clone();

 

print $obj->id . "\n";

print $obj->name . "\n";

print $obj->address . "\n";

?>

统一的构造方法名

ZEND引擎允许开发者定义类的构造方法。具有构造方法的类在新建时会首先调用构造方法,构造方法适用于在正式使用该类前进行的初始化。

在PHP4中,构造方法的名称与类名相同。由于在派生类中调用父类的作法比较普遍,因此导致在PHP4中当类在一个大型的类继承中进行移动时,处理方式有 点笨拙。当一个派生类被移动到一个不同的父类中时,父类的构造方法名必然是不同的,这样的话派生类中的有关调用父类构造方法的语句需要改写。

PHP 5 introduces a standard way of declaring constructor methods by calling them by the name __construct().

PHP5引入了方法名__construct()来定义构造方法。

Example

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();

?>

为向下兼容,PHP5当在类不能找到__construct()方法时,会通过老的方法也就是类名来查找构造方法。这意味着唯一可能产生兼容性问题的是在以前的代码中已经使用了一个名为__construct()的方法名。

---------------------------------------------------------------------------------

析构方法

定义析构方法是十分有用的。析构方法可以记录调试信息,关闭数据库连接,还有做其它的扫尾工作。PHP4中并无此机制,尽管PHP已支持注册在请求结束时需要运行的函数。

PHP 5 introduces a destructor concept similar to that of other object-oriented languages, such as Java: When the last reference to an object is destroyed the objects destructor, which is a class method name %__destruct()% that recieves no parameters, is called before the object is freed from memory.

PHP5引入了与其它面向对象语言如Java语言相似的析构方法:当最后一个该对象的引用被清除时,系统将会在该对象从内存中释放前调用名为__destruct()的析构方法。

例:

class MyDestructableClass {

function __construct() {

print "In constructor\n";

$this->name = "MyDestructableClass";

}

 

function __destruct() {

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

}

}

 

$obj = new MyDestructableClass();

?>

和构造方法相似,引擎将不调用父类的析构方法,为调用该方法,你需要在子类的析构方法中通过parent::__destruct()语句进行调用。

常量

PHP 5 引入了类常量定义:

class Foo {

const constant = "constant";

}

 

echo "Foo::constant = " . Foo::constant . "\n";

?>

 

PHP5允许常量中有表达式,但在编译时常量中的表达式将被计算.,因此常量不能在运行中改变它的值。

class Bar {

const a = 1<<0;

const b = 1<<1;

const c = a | b;

}

?>

以前代码中的用户自定义类或方法中虽未定义"const”关键字,但无需编辑即可运行。

例外

PHP 4 had no exception handling. PHP 5 introduces a exception model similar to that of other programming languages.

PHP4中无例外处理,PHP5引用了与其它语言相似的例外处理模型。

例:

class MyExceptionFoo extends Exception {

function __construct($exception) {

parent::__construct($exception);

}

}

 

try {

throw new MyExceptionFoo("Hello");

} catch (MyException $exception) {

print $exception->getMessage();

}

?>

以前代码中的用户自定义类或方法中虽未定义catch, throw 和 try关键字,但无需编辑即可运行。

函数返回对象值

In PHP 4 it wasnt possible to dereference objects returned by functions and make further method calls on those objects. With the advent of Zend Engine 2, the following is now possible:

在PHP4中,函数不可能返回对象的值并对返回的对象进行方法调用,通过ZEND引擎2中,这一切变得可能:

class Circle {

function draw() {

print "Circle\n";

}

}

 

class Square {

function draw() {

print "Square\n";

}

}

 

function ShapeFactoryMethod($shape) {

switch ($shape) {

case "Circle":

return new Circle();

case "Square":

return new Square();

}

}

 

ShapeFactoryMethod("Circle")->draw();

ShapeFactoryMethod("Square")->draw();

?>

静态类中的静态成员变量现在可初始化

Example

class foo {

static $my_static = 5;

}

 

print foo::$my_static;

?>

静态方法

PHP5引入了关键字static来定义一个静态方法,这样可以从对象外进行调用

例:

class Foo {

public static function aStaticMethod() {

// ...

}

}

 

Foo::aStaticMethod();

?>

虚拟变量$this在静态方法中无效。

instanceof

PHP5引入了关键字instanceof来确定一个对象是否是某一个对象的实例,或某一个对象的派生,或使用了某一个接口。

例:

class baseClass { }

$a = new baseClass;

if ($a instanceof basicClass) {

echo "Hello World";

}

?>

静态函数变量

所有的静态变量现在在编译时进行处理,这允许开发者通过引用来指定静态变量。这个变化提高了效率但意味着不可能对静态变量进行间接引用。

函数中通过按地址传送方式的参数允许定义默认值

例:

function my_function(&$var = null) {

if ($var === null) {

die("$var needs to have a value");

}

}

?>

__autoload()

在初始化一个未定义的类时,引擎将自动调用__autoload()拦截器函数。该类名将作为__autoload()拦截器函数唯一参数传递给它。

例:

function __autoload($className) {

include_once $className . ".PHP";

}

 

$object = new ClassName;

?>

方法和属性调用的重载

通用 __call(), __get() 和 __set()方法可以进行方法和属性调用的重载。

 

例: __get() 和 __set()

class Setter {

public $n;

public $x = array("a" => 1, "b" => 2, "c" => 3);

 

function __get($nm) {

print "Getting [$nm]\n";

 

if (isset($this->x[$nm])) {

$r = $this->x[$nm];

print "Returning: $r\n";

return $r;

} else {

print "Nothing!\n";

}

}

 

function __set($nm, $val) {

print "Setting [$nm] to $val\n";

 

if (isset($this->x[$nm])) {

$this->x[$nm] = $val;

print "OK!\n";

} else {

print "Not OK!\n";

}

}

}

 

$foo = new Setter();

$foo->n = 1;

$foo->a = 100;

$foo->a++;

$foo->z++;

var_dump($foo);

?>

例: __call()

class Caller {

var $x = array(1, 2, 3);

 

function __call($m, $a) {

print "Method $m called:\n";

var_dump($a);

return $this->x;

}

}

 

$foo = new Caller();

$a = $foo->test(1, "2", 3.4, true);

var_dump($a);

?>

 


原文地址:https://www.cnblogs.com/kafeijiu/p/3114941.html