PHP 5 引入了新的对象模型(Object Model)。完全重写了 PHP 处理对象的方式,允许更佳性能和更多特性。
<?php
class A
{
function foo ()
{
if (isset( $this )) {
echo '$this is defined (' ;
echo get_class($this );
echo ")\n";
} else {
echo "\$this is not defined.\n";
}
}
}
class B
{
function bar()
{
A ::foo();
}
}
$a = new A();
$a ->foo ();
A ::foo ();
$b = new B();
$b -> bar();
B :: bar();
?>
output:
$this is defined (a)$this is not defined.
$this is defined (b)
$this is not defined.
简单的类定义
{
// 成员声明
public $var = 'a default value';
// 方法声明
public function displayVar() {
echo $this ->var;
}
}
<?php
$instance = new SimpleClass ()
?>
当把一个对象已经创建的实例赋给一个新变量时,新变量会访问同一个实例,就和用该对象赋值一样。此行为和给函数传递入实例时一样。可以用克隆给一个已创建的对象建立一个新实例。=用于克隆除非使用&来标示传递引用
extends
一个类可以在声明中用 extends 关键字继承另一个类的方法和成员。不能扩展多个类,只能继承一个基类
被继承的方法和成员可以通过用同样的名字重新声明被覆盖,除非父类定义方法时使用了 final 关键字。可以通过 parent:: 来访问被覆盖的方法或成员。
<?php
function __autoload ($class_name ) {
require_once $class_name . '.php';
}
$obj = new MyClass1();
$obj2 = new MyClass2 ();
?>
注: 如果子类中定义了构造函数则不会暗中调用其父类的构造函数。要执行父类的构造函数,需要在子类的构造函数中调用 parent::__construct()。
和构造函数一样,父类的析构函数不会被引擎暗中调用。要执行父类的析构函数,必须在子类的析构函数体中显式调用 parent::__destruct()。
<?php
class MyDestructableClass {
function __construct () {
print "In constructor\n" ;
$this-> name = "MyDestructableClass" ;
}
function __destruct() {
print "Destroying " . $this ->name . "\n" ;
}
}
$obj = new MyDestructableClass();
?>
Class members must be defined with public, private, or protected.
const CONST_VALUE = 'A constant value' ;
}
echo MyClass:: CONST_VALUE ;
Two special keywords self and parent are used to access members or methods from inside the class definition.
class OtherClass extends MyClass
{
public static $my_static = 'static var' ;
public static function doubleColon () {
echo parent::CONST_VALUE . "\n";
echo self::$my_static . "\n" ;
}
}
OtherClass::doubleColon ();
Declaring class members or methods as static makes them accessible without needing an instantiation of the class. A member declared as static can not be accessed with an instantiated class object (though a static method can). Static members and methods cannot be re-defined in subclasses.
It is possible to define constant values on a per-class basis remaining the same and unchangeable. Constants differ from normal variables in that you don't use the $ symbol to declare or use them. Like static members, constant values cannot be accessed from an instance of the object (using $object::constant).
<?php
class MyClass
{
const constant = 'constant value' ;
function showConstant() {
echo self::constant . "\n" ;
}
}
echo MyClass ::constant . "\n";
$class = new MyClass();
$class ->showConstant();
// echo $class::constant; is not allowed
?>
PHP 5 introduces abstract classes and methods. It is not allowed to create an instance of a class that has been defined as abstract. Any class that contains at least one abstract method must also be abstract. Methods defined as abstract simply declare the method's signature they cannot define the implementation.
When inheriting from an abstract class, all methods marked abstract in the parent's class declaration must be defined by the child; additionally, these methods must be defined with the same (or weaker) visibillity. For example, if the abstract method is defined as protected, the function implementation must be defined as either protected or public.
<?php
abstract class AbstractClass
{
// Force Extending class to define this method
abstract protected function getValue ();
abstract protected function prefixValue ( $prefix);
// Common method
public function printOut () {
print $this->getValue () . "\n" ;
}
}
class ConcreteClass1 extends AbstractClass
{
protected function getValue () {
return "ConcreteClass1" ;
}
public function prefixValue( $prefix ) {
return "{$prefix}ConcreteClass1" ;
}
}
class ConcreteClass2 extends AbstractClass
{
public function getValue() {
return "ConcreteClass2" ;
}
public function prefixValue ( $prefix) {
return "{$prefix}ConcreteClass2" ;
}
}
$class1 = new ConcreteClass1 ;
$class1->printOut ();
echo $class1-> prefixValue ('FOO_') . "\n" ;
$class2 = new ConcreteClass2 ;
$class2->printOut ();
echo $class2->prefixValue ( 'FOO_') . "\n";
?>
ConcreteClass1 FOO_ConcreteClass1 ConcreteClass2 FOO_ConcreteClass2
Object Interfaces
Object interfaces allow you to create code which specifies which methods a class must implement, without having to define how these methods are handled.
借口定义同标准的类定义相同,但是不需要定义方法的实现.所有的方法定义必须是public访问级别的.
<?php
// Declare the interface 'iTemplate'
interface iTemplate
{
public function setVariable ($name , $var );
public function getHtml($template );
}
// Implement the interface
// This will work
class Template implements iTemplate
{
private $vars = array();
public function setVariable ( $name, $var )
{
$this->vars [ $name] = $var;
}
public function getHtml ($template)
{
foreach( $this->vars as $name => $value ) {
$template = str_replace('{' . $name . '}' , $value, $template );
}
return $template ;
}
}
// This will not work
// Fatal error: Class BadTemplate contains 1 abstract methods
// and must therefore be declared abstract (iTemplate::getHtml)
class BadTemplate implements iTemplate
{
private $vars = array();
public function setVariable ( $name, $var )
{
$this-> vars[$name ] = $var;
}
}
?>
instanceof 用来测定一个给定的对象是否来自指定的对象类。
interface MyInterface {
public function Hello ( AbstractClass $obj );
}
mixed __get ( string name )
bool __isset ( string name )
void __unset ( string name )
<?php
class Setter
{
public $n ;
private $x = array( "a" => 1 , "b" => 2 , "c" => 3 );
private function __get ($nm)
{
echo "Getting [$nm]\n";
if (isset($this ->x[$nm ])) {
$r = $this-> x[ $nm];
print "Returning: $r\n" ;
return $r ;
} else {
echo "Nothing!\n" ;
}
}
private function __set( $nm, $val)
{
echo "Setting [$nm] to $val\n" ;
if (isset( $this->x [$nm])) {
$this ->x[ $nm] = $val ;
echo "OK!\n" ;
} else {
echo "Not OK!\n";
}
}
private function __isset($nm )
{
echo "Checking if $nm is set\n" ;
return isset( $this->x [$nm ]);
}
private function __unset($nm )
{
echo "Unsetting $nm\n" ;
unset($this->x [ $nm]);
}
}
$foo = new Setter ();
$foo-> n = 1;
$foo ->a = 100 ;
$foo ->a++;
$foo->z ++;
var_dump(isset( $foo-> a)); //true
unset($foo ->a);
var_dump (isset($foo-> a )); //false
// this doesn't pass through the __isset() method
// because 'n' is a public property
var_dump(isset( $foo->n ));
var_dump($foo );
?>
Setting [a] to 100
OK!
Getting [a]
Returning: 100
Setting [a] to 101
OK!
Getting [z]
Nothing!
Setting [z] to 1
Not OK!
Checking if a is set
bool(true)
Unsetting a
Checking if a is set
bool(false)
bool(true)
object(Setter)#1 (2) {
["n"]=>
int(1)
["x:private"]=>
array(2) {
["b"]=>
int(2)
["c"]=>
int(3)
}
}
<?php
class Caller
{
private $x = array(1 , 2 , 3);
public 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);
?>
Method test called:
array(4) {
[0]=>
int(1)
[1]=>
string(1) "2"
[2]=>
float(3.4)
[3]=>
bool(true)
}
array(3) {
[0]=>
int(1)
[1]=>
int(2)
[2]=>
int(3)
}
<?php
class MyClass
{
public $var1 = 'value 1' ;
public $var2 = 'value 2' ;
public $var3 = 'value 3' ;
protected $protected = 'protected var' ;
private $private = 'private var' ;
function iterateVisible() {
echo "MyClass::iterateVisible:\n";
foreach( $this as $key => $value ) {
print "$key => $value\n" ;
}
}
}
$class = new MyClass ();
foreach( $class as $key => $value) {
print "$key => $value\n" ;
}
echo "\n" ;
$class ->iterateVisible ();
?>
var1 => value 1
var2 => value 2
var3 => value 3
MyClass::iterateVisible:
var1 => value 1
var2 => value 2
var3 => value 3
protected => protected var
private => private var
Object Iteration implementing Iterator
- class MyIterator implements Iterator
{
private $var = array();
public function __construct($array)
{
if ( is_array ($array)) {
$this-> var = $array ;
}
}
public function rewind () {
echo "rewinding\n" ;
reset($this->var);
}
public function current () {
$var = current ($this->var);
echo "current: $var\n" ;
return $var;
}
public function key () {
$var = key( $this->var);
echo "key: $var\n" ;
return $var;
}
public function next () {
$var = next($this ->var);
echo "next: $var\n" ;
return $var;
}
public function valid () {
$var = $this->current () !== false;
echo "valid: {$var}\n" ;
return $var;
}
}
$values = array( 1, 2,3);
$it = new MyIterator($values );
foreach ( $it as $a => $b) {
print "$a: $b\n" ;
}output:rewinding
current: 1
valid: 1
current: 1
key: 0
0: 1
next: 2
current: 2
valid: 1
current: 2
key: 1
1: 2
next: 3
current: 3
valid: 1
current: 3
key: 2
2: 3
next:
current:
valid:
{
private $items = array();
private $count = 0;
// Required definition of interface IteratorAggregate
public function getIterator() {
return new MyIterator ($this->items);
}
public function add($value ) {
$this ->items[$this->count++] = $value ;
}
}
{
// The factory method
public static function factory( $type )
{
if (include_once 'Drivers/' . $type . '.php') {
$classname = 'Driver_' . $type;
return new $classname ;
} else {
throw new Exception ('Driver not found' );
}
}
}
$mysql = Example::factory ('MySQL' );
// Load a SQLite Driver
$sqlite = Example::factory( 'SQLite' );
<?php
class Example
{
// Hold an instance of the class
private static $instance ;
// A private constructor; prevents direct creation of object
private function __construct()
{
echo 'I am constructed';
}
// The singleton method
public static function singleton ()
{
if (!isset( self::$instance )) {
$c = __CLASS__;
self::$instance = new $c;
}
return self :: $instance;
}
// Example method
public function bark()
{
echo 'Woof!' ;
}
// Prevent users to clone the instance
public function __clone()
{
trigger_error ('Clone is not allowed.' , E_USER_ERROR );
}
}
?>
$test = new Example ;
// This will always retrieve a single instance of the class
$test = Example ::singleton ();
$test->bark ();
// This will issue an E_USER_ERROR.
$test_clone = clone( $test);
toomuchphp-phpman at yahoo dot com 27-Nov-2005 05:46
// Each instance of 'Customer' represents one customer!
class Customer {
// Access a unique instance of class for a customer record
public function Unique( $CustomerID ) {
static $instances = array();
// a unique instance for each CustomerID
if(!isset($instances [ $CustomerID]))
$instances [$CustomerID] = new Customer ( $CustomerID);
return $instances[ $CustomerID ];
}
private $CustomerID ;
private function __construct( $CustomerID ) {
$this ->CustomerID = $CustomerID ;
}
}
// get instance of class for customer #1
$C1 = Customer :: Unique(1 );
// get instance of class for customer #2
$C2 = Customer :: Unique(2 );
<?php
class BaseClass {
public function test () {
echo "BaseClass::test() called\n" ;
}
final public function moreTesting () {
echo "BaseClass::moreTesting() called\n" ;
}
}
class ChildClass extends BaseClass {
public function moreTesting () {
echo "ChildClass::moreTesting() called\n" ;
}
}
// Results in Fatal error: Cannot override final method BaseClass::moreTesting()
?>
<?php
class SubObject
{
static $instances = 0;
public $instance;
public function __construct () {
$this-> instance = ++self ::$instances;
}
public function __clone() {
$this ->instance = ++self ::$instances;
}
}
class MyCloneable
{
public $object1;
public $object2 ;
function __clone()
{
// Force a copy of this->object, otherwise
// it will point to same object.
$this->object1 = clone( $this->object1 );
}
}
$obj = new MyCloneable();
$obj ->object1 = new SubObject ();
$obj-> object2 = new SubObject ();
$obj2 = clone $obj;
print("Original Object:\n" );
print_r( $obj);
print("Cloned Object:\n" );
print_r( $obj2);
?>
上例将输出:
Original Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 1
)
[object2] => SubObject Object
(
[instance] => 2
)
)
Cloned Object:
MyCloneable Object
(
[object1] => SubObject Object
(
[instance] => 3
)
[object2] => SubObject Object
(
[instance] => 2
)
)
When using the comparison operator (==), object variables are compared in a simple manner, namely: Two object instances are equal if they have the same attributes and values, and are instances of the same class.
相同的属性和相同的值,相同类的实例
On the other hand, when using the identity operator (===), object variables are identical if and only if they refer to the same instance of the same class.
相同类的相同实例
<?php
function bool2str($bool )
{
if ($bool === false ) {
return 'FALSE' ;
} else {
return 'TRUE';
}
}
function compareObjects(&$o1 , &$o2)
{
echo 'o1 == o2 : ' . bool2str( $o1 == $o2 ) . "\n";
echo 'o1 != o2 : ' . bool2str( $o1 != $o2) . "\n";
echo 'o1 === o2 : ' . bool2str( $o1 === $o2) . "\n";
echo 'o1 !== o2 : ' . bool2str( $o1 !== $o2) . "\n";
}
class Flag
{
public $flag ;
function Flag( $flag = true) {
$this->flag = $flag;
}
}
class OtherFlag
{
public $flag ;
function OtherFlag( $flag = true ) {
$this-> flag = $flag;
}
}
$o = new Flag ();
$p = new Flag();
$q = $o;
$r = new OtherFlag();
echo "Two instances of the same class\n";
compareObjects($o, $p);
echo "\nTwo references to the same instance\n" ;
compareObjects ($o, $q );
echo "\nInstances of two different classes\n" ;
compareObjects($o , $r);
?>
上例将输出:
Two instances of the same class o1 == o2 : TRUE o1 != o2 : FALSE o1 === o2 : FALSE o1 !== o2 : TRUE Two references to the same instance o1 == o2 : TRUE o1 != o2 : FALSE o1 === o2 : TRUE o1 !== o2 : FALSE Instances of two different classes o1 == o2 : FALSE o1 != o2 : TRUE o1 === o2 : FALSE o1 !== o2 : TRUE
php5中=传递的是对象的引用;
PHP 5 comes with a complete reflection API that adds the ability to reverse-engineer classes, interfaces, functions and methods as well as extensions. Additionally, the reflection API also offers ways of retrieving doc comments for functions, classes and methods.
The reflection API is an object-oriented extension to the Zend Engine, consisting of the following classes:
<?php
class Reflection { }
interface Reflector { }
class ReflectionException extends Exception { }
class ReflectionFunction implements Reflector { }
class ReflectionParameter implements Reflector { }
class ReflectionMethod extends ReflectionFunction { }
class ReflectionClass implements Reflector { }
class ReflectionObject extends ReflectionClass { }
class ReflectionProperty implements Reflector { }
class ReflectionExtension implements Reflector { }
?>
例子 19-31. Basic usage of the reflection API
<?php
Reflection ::export(new ReflectionClass ('Exception'));
?>
上例将输出:
Class [ <internal> class Exception ] { - Constants [0] { } - Static properties [0] { } - Static methods [0] { } - Properties [6] { Property [ <default> protected $message ] Property [ <default> private $string ] Property [ <default> protected $code ] Property [ <default> protected $file ] Property [ <default> protected $line ] Property [ <default> private $trace ] } - Methods [9] { Method [ <internal> final private method __clone ] { } Method [ <internal> <ctor> public method __construct ] { - Parameters [2] { Parameter #0 [ <required> $message ] Parameter #1 [ <required> $code ] } } Method [ <internal> final public method getMessage ] { } Method [ <internal> final public method getCode ] { } Method [ <internal> final public method getFile ] { } Method [ <internal> final public method getLine ] { } Method [ <internal> final public method getTrace ] { } Method [ <internal> final public method getTraceAsString ] { } Method [ <internal> public method __toString ] { } } }
ReflectionException extends the standard Exception and is thrown by Reflection API. No specific methods or properties are introduced。
The ReflectionFunction class lets you reverse-engineer functions.
The ReflectionParameter class retrieves information about a function's or method's parameters.
....
PHP 5 introduces Type Hinting. Functions are now able to force parameters to be objects (by specifying the name of the class in the function prototype) or arrays (since PHP 5.1).
php5允许定义方法的参数类型,但只能定义是class或是array。<?php
// An example class
class MyClass
{
/**
* A test function
*
* First parameter must be an object of type OtherClass
*/
public function test( OtherClass $otherclass) {
echo $otherclass ->var;
}
/**
* Another test function
*
* First parameter must be an array
*/
public function test_array(array $input_array ) {
print_r( $input_array);
}
}
// Another example class
class OtherClass {
public $var = 'Hello World' ;
}
?>
--
[:p] --飞扬.轻狂 [fallseir.lee]
http://fallseir.livejournal.com/
http://feed.feedsky.com/fallseir
没有评论:
发表评论