类与对象(PHP5)

第19章 类与对象(PHP5)之九:模式(Patterns)

模式是最好的实践和设计的描述方法。它给普通的编程问题展示一个可变的解决方案。
工厂模式(Factory)
工厂模式允许在运行的时间实例化一个对象。自从工厂模式命名以来,制造一个对象是可能的。
例子 19-23.工厂方法 (Factory Method)
复制PHP内容到剪贴板
PHP代码:

<?php
class Example
{   public static function factory($type)//The factory method
    
{   if (include_once 'Drivers/'.$type.'.php'
         {    
$classname 'Driver_' $type;
            return new 
$classname;
        }else{   throw new 
Exception ('Driver not found');  }
    }
}
?>

在类中允许定义一个驱动器在不工作时被加载的方法。如果类例子是一个数据库抽象类,可以象如下这样加载一个MySQL和SQLite驱动
复制PHP内容到剪贴板
PHP代码:

<?php
 $mysql 
Example::factory('MySQL'); // Load a MySQL Driver
 
$sqlite Example::factory('SQLite'); // Load a SQLite Driver
?>

单独模式(Singleton)
单模式适用于需要一个类的单独接口的情况。最普通的例子是数据库连接。这个模式的实现
允许程序员构造一个通过许多其他对象轻松地访问的单独接口。
例子 19-24.单模式函数(Singleton Function)
复制PHP内容到剪贴板
PHP代码:

<?php
class Example
{   // Hold an instance of the class
    
private static $instance;
    private function 
__construct()//A private constructor;prevents direct creation of object 
    
{   echo 'I am constructed';   }
     public static function 
singleton()// The singleton method 
    
{   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);  }
}
?>

允许类实例的一个单独接口被重新获得。
复制PHP内容到剪贴板
PHP代码:

<?php
$test 
= new Example// This would fail because the constructor is private
$test Example::singleton();// This will always retrieve a single instance of the class
$test->bark();
$test_clone = clone($test); // This will issue an E_USER_ERROR.
?>
 

第19章 类与对象(PHP5) 之十:魔法方法(Magic Methods)

函数名__construct, __destruct (注意构造函数和析构函数), __call, __get, __set, __isset, __unset (注意重载), __sleep, __wakeup, __toString, __set_state, __clone and __autoload是PHP类里边的魔法函数.
函数名 __construct, __destruct(注意构造函数和析构函数), __call, __get, __set, __isset, __unset (see 注意重载), __sleep, __wakeup, __toString, __set_state, __clone and __autoload在PHP类里是魔术的.在任何类里你不能用这些名字给函数命名除非你想与它们的魔术功能性相关联。
    注意: PHP储量将所有用__开始的函数名作为魔术函数。推荐地,在PHP里不能用__做函数名除非你想用文件证明是魔术函数。
__sleep()和__wakeup()
serialize() 检查类中是否有魔术名称 __sleep 的函数。如果这样,该函数将在任何序列化之前运行。它可以清除对象并应该返回一个包含有该对象中应被序列化的所有变量名的数组。
使用 __sleep 的目的是关闭对象可能具有的任何数据库连接,提交等待中的数据或进行类似的清除任务。此外,如果有非常大的对象而并不需要完全储存下来时此函数也很有用。
相反地,unserialize() 检查具有魔术名称 __wakeup 的函数的存在。如果存在,此函数可以重建对象可能具有的任何资源。
使用 __wakeup 的目的是重建在序列化中可能丢失的任何数据库连接以及处理其它重新初始化的任务。
例子 19-25. Sleep and wakeup
复制PHP内容到剪贴板
PHP代码:

<?php
class Connection 
{   protected $link;
    private 
$server$username$password$db;
    public function 
__construct($server$username$password$db)
    {   
$this->server $server;
        
$this->username $username;
        
$this->password $password;
        
$this->db $db;
        
$this->connect();
    }
    private function 
connect()
    {   
$this->link mysql_connect($this->server$this->username$this->password);
        
mysql_select_db($this->db$this->link);
    }
    public function 
__sleep() {   mysql_close($this->link);   }
    public function 
__wakeup() {   $this->connect();   }
}
?>

__toString
__toString方法允许一个类决定当它被修改为string类型时是如何起作用的。
例子 19-26.Simple example
复制PHP内容到剪贴板
PHP代码:

<?php
class TestClass// Declare a simple class
{   public $foo;
    public function 
__construct($foo){  $this->foo $foo;  }
    public function 
__toString()     {  return $this->foo;   }
}
$class = new TestClass('Hello');
echo 
$class;
?>

上例将输出:Hello
__toString方法将只在使用echo()和print()直接地组合时被调用是一个有效的注释方法。
例子 19-27. Cases where __toString is called
复制PHP内容到剪贴板
PHP代码:

<?php
echo $class//__toString called
echo 'text',$class//__toString called (still a normal parameter for echo)
echo 'text'.$class// __toString not called (concatenation operator used first)
echo (string)$class//__toString not called (cast to string first)
echo "text $class";//__toString not called (cast to string first)
?>

__set_state
从PHP 5.1.0开始static方法是通过var_export()函数来访问类接口的。这个方法的唯一参数是一个包含属性出口的以为array(‘property’=value,…)形式的数组

 

 

 

第19章:类与对象(PHP5)之十一:最终关键字(Final Keyword)

PHP5引入了最终关键字,防止子类使用final从一个重要的方法做定义的前缀。如果类本身已经被定义为final,类将不能被扩展。
例子 19-28.Final方法实例
复制PHP内容到剪贴板
PHP代码:

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

例子 19-29. Final 类实例
复制PHP内容到剪贴板
PHP代码:

<?php
final class BaseClass 
{    public function test()
     {  
         echo 
"BaseClass::test() called\n";  
     }
   
//Here it doesn't matter if you specify the function as final or not
   
final public function moreTesting()
   {
       echo
"BaseClass::moreTesting() called\n";
   }
}
class 
ChildClass extends BaseClass {  }
//Results in Fatal error:Class ChildClass may not inherit from final class (BaseClass)
?>

[ 本帖最后由 forest 于 2006-5-4 18:29 编辑 ]
 
 

 

第19章 类与对象(PHP5)之十二:对象克隆(Object cloning)

通过完全地复制属性创建一个对象的拷贝不是通常想要的行为。需求的一个好的实例适合于拷贝构造函数,
如果有一个对象描述一个GTK窗口和对象保存这个GTK窗口的资源,当你创建一个副本,你或许想创建一个相同的属性新窗口使用和保存新对象资源的新窗口。另一个例子是当你复制父对象时如果保存一个引用给另一个对象,你想创建其他类的一个新实例来分开拷贝所属的复制品。一个对象的拷贝是使用clone关键字来创建的(如果可能的话可以调用对象的__clone()方法),一个对象的__clone()方法不能被直接声明。
复制PHP内容到剪贴板
PHP代码:
$copy_of_object = clone $object;

当一个对象被克隆时,PHP5将执行一个所有对象的属性的浅拷贝。任何对其它变量引用的属性将只保留引用。如果一个__clone()方法被定义,然后重新创建一个对象的克隆方法来允许任何必需的属性当它需要被改变时调用。
例子 19-30. 克隆一个对象
复制PHP内容到剪贴板
PHP代码:

<?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()
    {
       
$this->object1=clone($this->object1);//Force a copy of this->object,otherwise it will point to same object.
    
}
}
$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
        )
)

 

 


 

第19章:类与对象(PHP5)之十三:对象比较(Comparing objects)

 

在PHP5中,对象的比较比PHP4中的更复杂和更协调的期望的一个面向对象语言(倒不是说PHP5是这样的一门语言)。当使用比较操作符(==),对象变量以一种简单的方式被比较。也就是:如果它们具有相同的属性和值,两个对象的实例是相等,并且是同一个类的实例。
另一方面,当使用恒等式操作符(===)时,对象变量当且仅当它们引用同一个类的同一个实例时是相同的
一个例子就可以阐明这些规则
例子 19-31.PHP5中的对象比较实例
复制PHP内容到剪贴板
PHP代码:

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

第19章 类与对象(PHP5)之十四:映射(反射)Reflection

介绍(Introduction)
PHP 5与一个API完全映射来以增加反向工程师类,接口,函数和方法的效率(性能)并加以扩展。另外, API映射并且为函数,类和方法提供获取文档注释的方法。
API映射是对Zend引擎一个面向对象的扩展。包括以下类:
复制PHP内容到剪贴板
PHP代码:

<?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-32.API映射的基本用法
复制PHP内容到剪贴板
PHP代码:

<?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)
ReflectionException 扩展标准异常并由API映射抛出。引入了非特定方法或属性。
映射函数(ReflectionFunction)
ReflectionFunction类允许你反向设计函数。
复制PHP内容到剪贴板
PHP代码:

<?php
class ReflectionFunction implements Reflector
{
    final private 
__clone()
    public 
object __construct(string name)
    public 
string __toString()
    public static 
string export()
    public 
string getName()
    public 
bool isInternal()
    public 
bool isUserDefined()
    public 
string getFileName()
    public 
int getStartLine()
    public 
int getEndLine()
    public 
string getDocComment()
    public array 
getStaticVariables()
    public 
mixed invoke(mixedargs)
    public 
mixed invokeArgs(array args)
    public 
bool returnsReference()
    public 
ReflectionParameter[] getParameters()
    public 
int getNumberOfParameters()
    public 
int getNumberOfRequiredParameters()
}
?>

注:getNumberOfParameters()和getNumberOfRequiredParameters()在PHP5.0.3中增加,而invokeArgs()是在PHP5.1.0中增加。
为内省一个函数,您必须首先创建ReflectionFunction 类的一个实例。您可以随后访问这个实例中的任何上述方法。
例子 19-33. 使用ReflectionFunction 类
复制PHP内容到剪贴板
PHP代码:

<?php
/** A simple counter
 * @return  int  */
function counter() 
{   static 
$c 0;
    return 
$c++;
}
// Create an instance of the Reflection_Function class
$func = new ReflectionFunction('counter');
// Print out basic information
printf(
    
"===> The %s function '%s'\n".
    
"     declared in %s\n".
    
"     lines %d to %d\n",
    
$func->isInternal() ? 'internal' 'user-defined',
    
$func->getName(),
    
$func->getFileName(),
    
$func->getStartLine(),
    
$func->getEndline()
);
// Print documentation comment
printf("--->Documentation:\n%s\n",var_export($func->getDocComment(),1));
if (
$statics=$func->getStaticVariables())//Print static variables if existant
{  printf("--->Static variables:%s\n",var_export($statics,1));  }
printf("--->Invokation results in:");//Invoke the function
var_dump($func->invoke());
//you may prefer to use the export() method
echo "\nReflectionFunction::export() results:\n";
echo 
ReflectionFunction::export('counter');
?>

注:方法invoke()通过象call_user_func()这样的函数接受自变量的一个变化的数值。
映射参数 (ReflectionParameter)
ReflectionParameter类取回一个函数或方法的参数的信息。
复制PHP内容到剪贴板
PHP代码:

<?php
class ReflectionParameter implements Reflector
{
    final private 
__clone()
    public 
object __construct(string name)
    public 
string __toString()
    public static 
string export()
    public 
string getName()
    public 
bool isPassedByReference()
    public 
ReflectionClass getClass()
    public 
bool isArray()
    public 
bool allowsNull()
    public 
bool isOptional()
    public 
bool isDefaultValueAvailable()
    public 
mixed getDefaultValue()
}
?>

注: 在PHP 5.0.3中增加了getDefaultValue(), isDefaultValueAvailable()和isOptional(),而isArray()则是在PHP5.1.0中增加的。
为内省函数参数,你必须首先创建ReflectionFunction或ReflectionMethod类的一个实例,然后用getParameters()方法来返回一个数组型参数。
例子 19-34. Using the ReflectionParameter class
复制PHP内容到剪贴板
PHP代码:

<?php
function foo($a$b$c) { }
function 
bar(Exception $a, &$b$c) { }
function 
baz(ReflectionFunction $a$b 1$c null) { }
function 
abc() { }
//通过命令行用给定的参数创建ReflectionFunction的一个实例   
$reflect = new ReflectionFunction($argv[1]);
echo 
$reflect;
foreach (
$reflect->getParameters() as $i => $param)
{    
printf"-- Parameter #%d: %s {\n".
        
"   Class: %s\n".
        
"   Allows NULL: %s\n".
        
"   Passed to by reference: %s\n".
        
"   Is optional?: %s\n".
        
"}\n",
        
$i
        
$param->getName(),
        
var_export($param->getClass(), 1),
        
var_export($param->allowsNull(), 1),
        
var_export($param->isPassedByReference(), 1),
        
$param->isOptional() ? 'yes' 'no');
}
?>

映射类(ReflectionClass)
ReflectionClass类允许你反向设计类。
复制PHP内容到剪贴板
PHP代码:

<?php
class ReflectionClass implements Reflector
{   final private __clone()
    public 
object __construct(string name)
    public 
string __toString()
    public static 
string export()
    public 
string getName()
    public 
bool isInternal()
    public 
bool isUserDefined()
    public 
bool isInstantiable()
    public 
bool hasConstant(string name)
    public 
bool hasMethod(string name)
    public 
bool hasProperty(string name)
    public 
string getFileName()
    public 
int getStartLine()
    public 
int getEndLine()
    public 
string getDocComment()
    public 
ReflectionMethod getConstructor()
    public 
ReflectionMethod getMethod(string name)
    public 
ReflectionMethod[] getMethods()
    public 
ReflectionProperty getProperty(string name)
    public 
ReflectionProperty[] getProperties()
    public array 
getConstants()
    public 
mixed getConstant(string name)
    public 
ReflectionClass[] getInterfaces()
    public 
bool isInterface()
    public 
bool isAbstract()
    public 
bool isFinal()
    public 
int getModifiers()
    public 
bool isInstance(stdclass object)
    public 
stdclass newInstance(mixedargs)
    public 
ReflectionClass getParentClass()
    public 
bool isSubclassOf(ReflectionClass class)
    public array 
getStaticProperties()
    public 
mixed getStaticPropertyValue(string name [, mixed default])
    public 
void setStaticPropertyValue(string namemixed value)
    public array 
getDefaultProperties()
    public 
bool isIterateable()
    public 
bool implementsInterface(string name)
    public 
ReflectionExtension getExtension()
    public 
string getExtensionName()
}
?>

注:PHP5.1.0中增加了hasConstant(), hasMethod(), hasProperty(), getStaticPropertyValue()和 setStaticPropertyValue()。
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值