function printHello() { MyClass::printHello(); /* Should print */ print "MyClass2::printHello() " . $this->Hello; /* Shouldn't print out anything */ print "MyClass2::printHello() " . $this->Bar; /* Shouldn't print (not declared)*/ print "MyClass2::printHello() " . $this->Foo; /* Should print */ } }
$obj = new MyClass(); print $obj->Hello; /* Shouldn't print out anything */ print $obj->Bar; /* Shouldn't print out anything */ print $obj->Foo; /* Shouldn't print out anything */ $obj->printHello(); /* Should print */
$obj = new MyClass2(); print $obj->Hello; /* Shouldn't print out anything */ print $obj->Bar; /* Shouldn't print out anything */ print $obj->Foo; /* Shouldn't print out anything */ $obj->printHello(); ?> 私有和保护方法 在PHP 5(ZEND引擎2)中,还引入了私有和保护方法。 例: <?php 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还引入了抽象类和方法。抽象方法只声明方法定义, 不供实际运行。包含抽象方法的类需要声明为抽象类。 例: <?php 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 例: <?php interface Throwable { public function getMessage(); }
class Exception implements Throwable { public function getMessage() { // ... } ?> 以前代码中的用户自定义类或方法中虽未定义"interface”关键字,但无需编辑即可运行。 类类型定义 在保留类无需定义类型的同时,PHP 5引入了类类型定义来声明希望把哪个类通过参数传递给一个方法。 Example 例: <?php 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); ?> 这些类类型定义在不象一些需要类型预定义的语言在编译中进行检查,而是在运行时进行。这意味着: <?php function foo(ClassName $object) { // ... } ?> 等价于: <?php function foo($object) { if (!($object instanceof ClassName)) { die("Argument 1 must be an instance of ClassName"); } } ?> 本语法只用于对象或类,不适用于内建类型。
final PHP 5引入了“final”关键字定义在子类中不能被覆盖的成员或方法。 例: <?php class Foo { final function bar() { // ... } } ?> 以前代码中的用户自定义类或方法中虽未定义"final"关键字,但无需编辑即可运行。 对象克隆 PHP 4在对象被复制时,用户不能决定拷贝的机制。在复制时,PHP 4只一位一位地复制一个和原来对象一模一样的复制品。 我们并不是每次都要建立一个完全一样的复制品。一个很好的需要一种复制机制的例子是,当有一个代表一个GTK窗口的对象,它拥有该窗口的所有资源,当你建立一个拷贝时,你可能需要一个新的窗口,它拥有原窗口的所有属性,但需要拥有新窗口的资源。另外一个例子是你有一个对象引用了另外一个对象,当你复制父对象时,你希望建立那个引用对象的新实例,以使复制品引用它。 对一个对象的拷贝通过调用对象的__clone()方法完成: <?php $copy_of_object = $object->__clone(); ?> 当开发者请求建立一个对象的新的拷贝时,ZEND引擎会检查是否定义了__clone()方法。如果未定义的话,它会调用一个默认的__clone()方法来复制该对象的所有属性。如果定义了该方法,该方法会负责在拷贝中设置必要的属性。为方便起见,引擎会提供一个函数从源对象中导入所有的属性,这样它就可以先得到一个具有值的源对象拷贝,只需要对需要改变的属性进行覆盖即可。 例: <?php 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 <?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(); ?> 为向下兼容,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 object's destructor, which is a class method name %__destruct()% that recieves no parameters, is called before the object is freed from memory. PHP5引入了与其它面向对象语言如Java语言相似的析构方法:当最后一个该对象的引用被清除时,系统将会在该对象从内存中释放前调用名为__destruct()的析构方法。 例: <?php class MyDestructableClass { function __construct() { print "In constructor\n"; $this->name = "MyDestructableClass"; }
PHP5允许常量中有表达式,但在编译时常量中的表达式将被计算.,因此常量不能在运行中改变它的值。 <?php 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引用了与其它语言相似的例外处理模型。 例: <?php 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 wasn't 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中,这一切变得可能: <?php 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 <?php class foo { static $my_static = 5; }
print foo::$my_static; ?> 静态方法 PHP5引入了关键字'static'来定义一个静态方法,这样可以从对象外进行调用。 例: <?php class Foo { public static function aStaticMethod() { // ... } }