The core of PHP's object processing part has been completely redeveloped to provide more functions and improve performance. In previous versions of PHP, objects were handled the same way as basic types (numbers, strings). The disadvantage of this method is that when assigning the object to a variable or passing the object through parameters, the object will be completely copied. In the new version, the above operation will pass a reference (reference can be understood as an identifier of the object) instead of a value.
Many PHP programmers may not even be aware of the old way of handling objects. In fact, most PHP applications will run just fine. Or only minimal changes are needed.
Private and protected members
PHP5 introduces the concept of private and protected member variables. We can use it to define the visibility of class members.
Example
Protected members can be accessed by subclasses, while private members can only be accessed by the class itself.
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::printH ello() " . $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 methods and protected methods
PHP5 also introduces the concepts of private methods and protected methods.
Example:
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 did not use classes before, no Code with access modifiers (public, protected, private) can run unchanged.
Abstract classes and abstract methods
Php5 also introduced the concepts of abstract classes and abstract methods. An abstract method only declares the signature of the method and does not provide its implementation. Classes containing abstract methods must be declared abstract.
Example:
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 class cannot be instantiated. Old code that did not use abstract classes can run unchanged.
Interface
Php5 introduced interface. A class can implement multiple interfaces.
Example:
interface Throwable {
public function getMessage();
}
class MyException implementations Throwable {
public function getMessage() {
>
Class type hints
PHP5 is still weakly typed, but when defining function parameters, you can use class type hints to declare the expected object type
Example
interface Foo {
function a(Foo $foo);
}
interface Bar {
function b(Bar $bar );
}
class FooBar implementations Foo, Bar {
function a(Foo $foo) {
function b (Bar $bar) {
a->a($b);
$a->b($b);
?>
Like other strongly typed languages, the type hints for php5 classes are in Checked during runtime rather than during compilation. That is:
function foo(ClassName $object) {
// ...
}
?>
and the following The code is the same:
function foo($object) {
if (!($object instanceof ClassName)) {
die("Argument 1 must be an instance of ClassName");
}
}
?>
This syntax only applies to classes, not built-in types.
Final
PHP 5 introduced the final keyword to declare final members and final methods. Final members and final methods cannot be overridden by subclasses.
Example
class Foo {
final function bar() {
;
Further, you can declare the class as final. Declaring a class final prevents the class from being inherited. The methods in the final class are final by default and do not need to be declared again.
Example
final class Foo {
// class definition
}
// the next line is impossible
// class Bork extends Foo {}
?>
Properties cannot be defined as final.
Old code that did not use final can be run without modification.
Object cloning
Php4 does not provide a mechanism for users to define their own copy constructor (copy constructor) to control the copying process of objects. Php4 does a binary copy, thus duplicating all properties of the object very accurately.
Copying exactly all properties of an object may not be what we always want. There is an example that illustrates that we do need a copy constructor: such as a GTK Window object a. a holds all the resources it needs. When copying this GTK Window to object b, we prefer that b hold a new resource object. Another example: object a contains an object c, when you copy object a to object c. We might prefer that object b contains a copy of a new object c, rather than a reference to object c. (Translator's Note: What we are talking about here are shallow cloning and deep cloning.)
The copy of the object is achieved through the clone keyword (Clone calls the __clone() method of the cloned object). The __clone method of an object cannot be called directly.
$copy_of_object = clone $object;
?>
When the developer creates a copy of the object, php5 will check __clone() method exists. If it does not exist, then it will call the default __clone() method to copy all attributes of the object.If the __clone() method has been defined, then the _clone() method will be responsible for setting the properties of the new object. For convenience, Engine copies all properties by default. So in the __clone() method, you only need to overwrite those properties that need to be changed. As follows:
Example
class MyCloneable {
static $id = 0;
function MyCloneable() {
$this->id = self ::$id++;
}
function __clone() {
$this->address = "New York";
$this->id = self::$id++ ;
}
}
$obj = new MyCloneable();
$obj->name = "Hello";
$obj->address = "Tel-Aviv";
print $obj->id . "n";
$obj_cloned = clone $obj;
print $obj_cloned->id . "n";
print $obj_cloned->name . "n";
print $obj_cloned->address . "n";
?>
Uniform constructor
Php5 allows developers to declare the constructor of a class. A class with a constructor will call this method every time it creates a new object, so the constructor is suitable for initializing the object before it is used
In Php4, the name of the constructor is the same as the name of the class. Considering that it is very common to call the parent class constructor from a subclass constructor, and changes to the parent class caused by relocating a class from an inheritance system often result in the need to change the class's constructor, php4's approach is obviously not very good. reasonable.
Php5 introduced a standard way to declare a constructor function: __construct(). As follows:
Example
class BaseClass {
function __construct() {
print "In BaseClass constructorn";
}
}
class SubClass extends BaseClass {
function __construct() {
parent::__construct();
print "In SubClass constructorn";
}
}
$obj = new BaseClass();
$obj = new SubClass();
?>
To maintain backward compatibility, if php5 cannot find __construct(), it will look for the old-fashioned constructor method, which is the method with the same name as the class. Simply put, there is a compatibility issue only when the old code contains a __construct() method.
Destruction method
For object-oriented programming, being able to define a destructor method is a very useful feature. The destructor method can be used to record debugging information, close database connections, and other cleanup work. There is no destructor method in Php4, although PHP4 already supports the ability to register a function to be called when the request ends.
The concept of destructor method introduced by Php5 is consistent with other object-oriented languages (such as java). When the last reference to this object is destroyed, the destructor method is called, and the memory is released after the call is completed. Note: The destructor method does not accept any parameters.
Example
class MyDestructableClass {
function __construct() {
print "In constructorn";
$this->name = "MyDestructableClass" ;
}
function __destruct() {
print "Destroying" . $this->name . "n";
}
}
$ obj = new MyDestructableClass();
?>
Like the construction method, the destructor method of the parent class will not be implicitly called. Subclasses can explicitly call it in their own destructor by calling parent::__destruct().
Constants
Php5 introduced class-level constants.
class Foo {
const constant = "constant";
}
echo "Foo::constant = " . Foo::constant . "n";
?>
Old code that does not use const still runs normally.
Exceptions
Php4 has no exception control. Php5 introduces an exception control model similar to other languages (java). It should be noted that php5 supports catching all exceptions, but does not support the finally clause.
In the catch statement block, exceptions can be re-thrown.There can also be multiple catch statements. In this case, the caught exceptions are compared with the catch statements from top to bottom. The first catch statement with a matching type will be executed. If no matching catch clause is found after searching to the end, look for the next try/catch statement. The last exception that cannot be caught will be displayed. If the exception is caught, the program will start executing below the catch statement block.
Example
class MyException {
function __construct($exception) {
$this->exception = $exception;
}
function Display() {
print "MyException: $this->exceptionn";
}
}
class MyExceptionFoo extends MyException {
function __construct($exception ) {
$this->exception = $exception;
}
function Display() {
print "MyException: $this->exceptionn";
}
}
try {
throw new MyExceptionFoo('Hello');
}
catch (MyException $exception) {
$exception->Display();
}
catch (Exception $exception) {
echo $exception;
}
?>
The above example shows that it is possible to define an exception that does not inherit from Exception class, however, it is better to inherit from Exception and define your own exceptions. This is because the system's built-in Exception class can collect a lot of useful information, and exception classes that do not inherit it cannot get this information. The following php code imitates the system's built-in Exception class. Each attribute is followed by a comment. Each property has a getter. Since these getter methods are often called by the system's internal processing, these methods are marked final.
Example
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
}
}
?>
如果我们定义的一异常类都是继承自Exception基类
无兼容性问题。老的代码不会受到这一特性的影响。
Dereferencing objects returned from functions
Php4中不能再次引用函数返回的对象以进一步呼叫返回对象的方法,而php5是可以的。
class Circle {
function draw() {
print "Circlen";
}
}
class Square {
function draw() {
print "Squaren";
}
}
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;
public $my_prop = 'bla';
}
print foo: :$my_static;
$obj = new foo;
print $obj->my_prop;
?>
Static method
PHP 5 introduced static methods, which can be used in Call a static method without instantiating the class.
Example
class Foo {
public static function aStaticMethod() {
🎜>Foo::aStaticMethod();
?>
The pseudo variable $this cannot be used in static methods.
instanceof
Php5 introduced the instanceof keyword, allowing it to be used to test that an object is an instance of a class, an instance of a derived class, or implements an interface
Example
class baseClass { }
$a = new baseClass;
if ($a instanceof baseClass) {
echo "Hello World";
}
?>
Static function variables
Now, static variables are processed during the compilation phase. So programmers can assign values to static variables by reference. This can improve performance, however, indirect references to static variables cannot be used.
Function parameters passed by reference can now also have default values set.
Example
function my_function(&$var = null) {
if ($var === null) {
die("$var needs to have a value");
}
}
?>
__autoload()
__autoload() The interception function is automatically called when an undeclared class is initialized. The name of the class is automatically passed to the __autoload() function. And __autoload() has only one parameter.
Example
function __autoload($className) {
include_once $className . ".php";
}
$object = new ClassName;
?>
Overloadable method calls and attribute access
Method calls and attribute access can be overloaded through the __call, __get() and __set() methods.
Example: __get() and __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: $rn";
return $r;
} else {
print "Nothing!n";
}
}
function __set($nm, $val) {
print "Setting [$nm] to $valn";
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()
class Caller {
private $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);
?>
迭代
当和foreach一起使用对象的时候,迭代的方式被重载过了。缺省的行为是迭代类的所有属性。
Example
class Foo {
public $x = 1;
public $y = 2;
}
$obj = new Foo;
foreach ($obj as $prp_name => $prop_value) {
// using the property
}
?>
一个类的所有对象都能够被迭代浏览到, 如果这个类实现了一个空的接口:Traversable. 换句话说,实现了Traversable接口的类可以和foreach一起使用。
接口 IteratorAggregate 和Iterator允许指定类的对象在代码中如何迭代。IteratorAggregate接口有一个方法:getIterator() 必须返回一个数组
Example
class ObjectIterator implements Iterator {
private $obj;
private $num;
function __construct($obj) {
$this->obj = $obj;
}
function rewind() {
$this->num = 0;
}
function valid() {
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 = $valn";
}
// 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 = $valn";
}
unset($it);
?>
新的__toString方法
可以通过覆盖__toString方法来控制对象到字符串的转换。
Example
class Foo {
function __toString() {
return "What ever";
}
}
$obj = new Foo;
echo $obj; // call __toString()
?>
Reflection API
Php5引入了全套的反射API,以支持对类,接口,函数,方法的反向工程。
它也提供了API以从程序中提取注释文档。反射API的详细资料参考此处:http://sitten-polizei.de/php/reflection_api/docs/language.reflection.html
Example
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');
?>
新内存管理机制
Php5有一个全新的内存管理机制,使得它在多线程的环境下可以更有效地运行。在分配和释放内存时,不再使用mutex锁定/解除锁定