Zend2的新功能介绍 读完以后,收益非浅

Changes in PHP 5/Zend Engine II 
By php.net

March 22, 2004
New Object Model
Private and Protected Members
Private and Protected Methods
Abstract Classes and Methods
Interfaces
Class Type Hints
final
Object Cloning
Unified Constructors
Destructors
Constants
Exceptions
Dereferencing Objects Returned from Functions
Static Member Variables of Static Classes Can Now be Initialized
Static Methods
instanceof
Static Function Variables
Parameters that are Passed by Reference to a Function May Now Have Default Values
__autoload()
Overloadable Method Calls and Property Accesses
Iteration
New __METHOD__ Constant
New __toString() Method
Reflection API
New Memory Manager

New Object Model

PHP's handling of objects has been completely rewritten, allowing for better performance and more features. In previous versions of PHP, objects were handled like primitive types (for instance integers and strings). The drawback of this method was that semantically the whole object was copied when a variable was assigned, or pass as a parameter to a method. In the new approach, objects are referenced by handle, and not by value (one can think of a handle as an object's identifier).

Many PHP programmers aren't even aware of the copying quirks of the old object model and, therefore, the majority of PHP applications will work out of the box, or with very few modifications.

Private and Protected Members

PHP 5 introduces private and protected member variables, they allow you to define the visibility of class properties.

Example

Protected member variables can be accessed in classes extending the class they are declared in, whereas private member variables can only be accessed by the class they belong to.

<?php
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; /* 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();
?>

Private and Protected Methods

With PHP 5, private and protected methods are also introduced.

Example

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

Old code that has no user-defined classes or functions named "public", "protected" or "private" should run without modifications.

Abstract Classes and Methods

PHP 5 also introduces abstract classes and methods. An abstract method only declares the method's signature and does not provide an implementation. A class that contains abstract methods needs to be declared abstract.

Example

<?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 classes cannot be instantiated. Old code that has no user-defined classes or functions named 'abstract' should run without modifications.

Interfaces

PHP 5 introduces interfaces. A class may implement an arbitrary list of interfaces.

Example

<?php
interface Throwable {
   public function
getMessage();
}

class
MyException implements Throwable {
   public function
getMessage() {
       
// ...
   
}
}
?>

Old code that has no user-defined classes or functions named 'interface' or 'implements' should run without modifications.

Class Type Hints

While remaining loosely typed PHP 5 introduces the ability to use class type hints to declare the expected class of objects that are passed as parameters to a method.

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

These class type hints are not checked upon compilation, as would be the case in a typed language, but during runtime. This means that:

<?php
function foo(ClassName $object) {
   
// ...
}
?>

is equivalent to:

<?php
function foo($object) {
   if (!(
$object instanceof ClassName)) {
       die(
"Argument 1 must be an instance of ClassName");
   }
}
?>

This syntax only applies to objects/classes, not built-in types.

final

PHP 5 introduces the "final" keyword to declare final members and methods. Methods and members declared final cannot be overridden by sub-classes.

Example

<?php
class Foo {
   
final function bar() {
       
// ...
   
}
}
?>

It is furthermore possible to make a class final. Doing this prevents a class from being specialized (it cannot be inherited by another class). There's no need to declare the methods of a final class themselves as final.

Example

<?php
final
class Foo {
   
// class definition
}

// the next line is impossible
// class Bork extends Foo {}
?>

Properties cannot be final.

Old code that has no user-defined classes or functions named 'final' should run without modifications.

Object Cloning

PHP 4 offered no way a user could decide what copy constructor to run when an object is duplicated. During duplication, PHP 4 did a bit for bit copy making an identical replica of all the object's properties.

Creating a copy of an object with fully replicated properties is not always the wanted behavior. A good example of the need for copy constructors, is if you have an object which represents a GTK window and the object holds the resource of this GTK window, when you create a duplicate you might want to create a new window with the same properties and have the new object hold the resource of the new window. Another example is if your object holds a reference to another object which it uses and when you replicate the parent object you want to create a new instance of this other object so that the replica has its own separate copy.

An object copy is created by calling the object's __clone() method:

<?php
$copy_of_object
= $object->__clone();
?>

When the developer asks to create a new copy of an object, PHP 5 will check if a __clone() method has been defined or not. If not, it will call a default __clone() which will copy all of the object's properties. If a __clone() method is defined, then it will be responsible to set the necessary properties in the created object. For convenience, the engine will supply a function that imports all of the properties from the source object, so that they can start with a by-value replica of the source object, and only override properties that need to be changed.

Example

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

Unified Constructors

PHP 5 allows developers to declare constructor methods for classes. Classes which have a constructor method call this method on each newly-created object, so it is suitable for any initialization that the object may need before it is used.

With PHP 4, constructor methods were class methods that had the same name as the class itself. Since it is very common to call parent constructors from derived classes, the way PHP 4 worked made it a bit cumbersome to move classes around in a large class hierarchy. If a class is moved to reside under a different parent, the constructor name of that parent changes as well, and the code in the derived class that calls the parent constructor has to be modified.

PHP 5 introduces a standard way of declaring constructor methods by calling them by the name __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();
?>

For backwards compatibility, if PHP 5 cannot find a __construct() function for a given class, it will search for the old-style constructor function, by the name of the class. Effectively, it means that the only case that would have compatibility issues is if the class had a method named __construct() which was used for different semantics.

Destructors

Having the ability to define destructors for objects can be very useful. Destructors can log messages for debugging, close database connections and do other clean-up work. No mechanism for object destructors existed in PHP 4, although PHP had already support for registering functions which should be run on request shutdown.

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 named __destruct() that receives no parameters, is called before the object is freed from memory.

Example

<?php
class MyDestructableClass {
   function
__construct() {
       print
"In constructor/n";
       
$this->name = "MyDestructableClass";
   }

   function
__destruct() {
       print
"Destroying " . $this->name . "/n";
   }
}

$obj = new MyDestructableClass();
?>

Like constructors, parent destructors will not be called implicitly by the engine. In order to run a parent destructor, one would have to explicitly call parent::__destruct() in the destructor body.

Constants

PHP 5 introduces per-class constants:

<?php
class Foo {
   const
constant = "constant";
}

echo
"Foo::constant = " . Foo::constant . "/n";
?>

Old code that has no user-defined classes or functions named 'const' will run without modifications.

Exceptions

PHP 4 had no exception handling. PHP 5 introduces a exception model similar to that of other programming languages. Note that there is support for "catch all" but not for the "finally" clause.

Exceptions can be rethrown in catch blocks. Also it is possible to have multiple catch blocks. In that case the caught exception is compared with the classtype of each catch block from top to bottom and the first block that has an 'instanceof' match gets executed. When the catch block finishes, execution continues at the end of the last catch block. If no catch block has an 'instanceof' match then the next try/catch block is searched until no more try/catch blocks are available. In that case the exception is an uncaught exception and the program terminates with showing the exception.

Example

<?php
class MyException {
   function
__construct($exception) {
       
$this->exception = $exception;
   }

   function
Display() {
       print
"MyException: $this->exception/n";
   }
}

class
MyExceptionFoo extends MyException {
   function
__construct($exception) {
       
$this->exception = $exception;
   }

   function
Display() {
       print
"MyException: $this->exception/n";
   }
}

try {
   
throw new MyExceptionFoo('Hello');
}
catch (MyException $exception) {
   
$exception->Display();
}
catch (Exception $exception) {
   echo
$exception;
}
?>

Even though the above example shows that it is possible to define exception classes that don't inherit from Exception it is best to do so. This is because the internal Exception class can gather a lot of information otherwise not available. The PHP code emulation code would look something like shown below. The comments show the meaning of each property and hence their getter methods. As the code shows it is possible to read any available information by using the getter methods. But since some of the methods are used internally they are marked final. All in all the class is very restrictive because it must be ensured that anything used internally always works as expected.

Example

<?php
class Exception {
   function
__construct(string $message=NULL, int code=0) {
       if (
func_num_args()) {
           
$this->message = $message;
       }
       
$this->code = $code;
       
$this->file = __FILE__; // of throw clause
       
$this->line = __LINE__; // of throw clause
       
$this->trace = debug_backtrace();
       
$this->string = StringFormat($this);
   }

   protected
$message = 'Unknown exception';  // exception message
   
protected $code = 0; // user defined exception code
   
protected $file;    // source filename of exception
   
protected $line;    // source line of exception

   
private $trace;      // backtrace of exception
   
private $string;    // internal only!!

   
final function getMessage() {
       return
$this->message;
   }
   final function
getCode() {
       return
$this->code;
   }
   final function
getFile() {
       return
$this->file;
   }
   final function
getTrace() {
       return
$this->trace;
   }
   final function
getTraceAsString() {
       return
self::TraceFormat($this);
   }
   function
_toString() {
       return
$this->string;
   }
   static
private function StringFormat(Exception $exception) {
       
// ... a function not available in PHP scripts
       // that returns all relevant information as a string
   
}
   static
private function TraceFormat(Exception $exception) {
       
// ... a function not available in PHP scripts
       // that returns the backtrace as a string
   
}
}
?>

If you derive your exception classes from this Exception base class your exceptions will be nicely shown in the built-in handler for uncaught exceptions.

Old code that has no user-defined classes or functions 'catch', 'throw' and 'try' will run without modifications.

Dereferencing Objects Returned from Functions

In PHP 4 it wasn't possible to dereference objects returned by functions and make further method calls on those objects. With PHP 5, the following is now possible:

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

Static Member Variables of Static Classes Can Now be Initialized

Example

<?php
class foo {
   static
$my_static = 5;
   public
$my_prop = 'bla';
}

print
foo::$my_static;
$obj = new foo;
print
$obj->my_prop;
?>

Static Methods

PHP 5 introduces the 'static' keyword to declare a method static, thus callable from outside the object context.

Example

<?php
class Foo {
   public static function
aStaticMethod() {
       
// ...
   
}
}

Foo::aStaticMethod();
?>

The pseudo variable $this is not available inside a method that has been declared static.

instanceof

PHP 5 introduces the instanceof keyword, that allows you to ascertain whether or not an object is an instance of a class, or extends a class, or implements an interface.

Example

<?php
class baseClass { }

$a = new baseClass;

if (
$a instanceof baseClass) {
   echo
"Hello World";
}
?>

Static Function Variables

Statics are now treated at compile-time which allows developers to assign variables to statics by reference. This change also greatly improves their performance but means that indirect references to statics will not work anymore.

Parameters that are Passed by Reference to a Function May Now Have Default Values

Example

<?php
function my_function(&$var = null) {
   if (
$var === null) {
       die(
"$var needs to have a value");
   }
}
?>

__autoload()

The __autoload() interceptor function will be automatically called when an undeclared class is to be instantiated. The name of that class will be passed to the __autoload() interceptor function as its only argument.

Example

<?php
function __autoload($className) {
   include_once
$className . ".php";
}

$object = new ClassName;
?>

Overloadable Method Calls and Property Accesses

Both method calls and property accesses can be overloaded via the __call(), __get() and __set() methods.

Example: __get() and __set()

<?php
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);
?>

Example

: __call()

<?php
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);
?>

Iteration

Objects may be iterated in an overloaded way when used with foreach. The default behavior is to iterate over all properties.

Example

<?php
class Foo {
   var
$x = 1;
   var
$y = 2;
}

$obj = new Foo;

foreach (
$obj as $prp_name => $prop_value) {
   
// using the property
}
?>

Each class whose instances can be iterated with foreach should implement the empty interface Traversable. Hence any object that says it implements Traversable can be used with foreach.

The interfaces IteratorAggregate and Iterator allows you to specify how class objects are iterated in PHP code. The first of them simply has a method getIterator() which must return an array or an object that either implements the interface Iterator or is instantiated from an internal class that can be iterated.

Example

<?php
class ObjectIterator implements Iterator {

   private
$obj;
   private
$num;

   function
__construct($obj) {
       
$this->obj = $obj;
   }
   function
rewind() {
       
$this->num = 0;
   }
   function
hasMore() {
       return
$this->num < $this->obj->max;
   }
   function
key() {
       return
$this->num;
   }
   function
current() {
       switch(
$this->num) {
           case
0: return "1st";
           case
1: return "2nd";
           case
2: return "3rd";
           default: return
$this->num."th";
       }
   }
   function
next() {
       
$this->num++;
   }
}

class
Object implements IteratorAggregate {

   public
$max = 3;

   function
getIterator() {
       return new
ObjectIterator($this);
   }
}

$obj = new Object;

// this foreach ...
foreach($obj as $key => $val) {
   echo
"$key = $val/n";
}

// matches the following 7 lines with the for directive.
$it = $obj->getIterator();
for(
$it->rewind(); $it->hasMore(); $it->next) {
   
$key = $it->current();
   
$val = $it->key();
   echo
"$key = $val/n";
}
unset(
$it);
?>

The matching for directive is very interesting here since it shows the use of all abstract methods declared in the interfaces Iterator and IteratorAggregate respectively.

New __METHOD__ Constant

The new __METHOD__ pseudo constant shows the current class and method when used inside a method and the function when used outside of a class.

Example

<?php
class Foo {
   function
Show() {
       echo
__FILE__ . '(' . __LINE__ . ')' . __METHOD__;
   }
}
function
Test() {
   echo
__FILE__ . '(' . __LINE__ . ')' . __METHOD__;
}
?>

New __toString() Method

The new __toString() magic method allows you to overload the object to string conversion.

Example

<?php
class Foo {
   function
__toString() {
       return
"What ever";
   }
}

$obj = Foo;

$str = (string) $obj; // call __toString()

echo $obj; // call __toString()
?>

Reflection API

PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions and methods as well as extensions.

The reflection API also offers ways of getting doc comments for functions, classes and methods.

Nearly all aspects of object oriented code can be reflected by using the reflection API which is documented separately.

Example

<?php
class Foo {
   public
$prop;
   function
Func($name) {
       echo
"Hello $name";
   }
}

reflection_class::export('Foo');
reflection_object::export(new Foo);
reflection_method::export('Foo', 'func');
reflection_property::export('Foo', 'prop');
reflection_extension::export('standard');
?>

New Memory Manager

PHP 5 has a new memory manager which allows it to run efficiently in multi-threaded environments as it doesn't need to use mutexes to lock and unlock during allocation/deallocation.

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值