下载本文示例代码
领会暗示 首先介绍一下对象类型和类型提示的优点。一个类定义一种类型。从该类实例化的任何对象属于该类定义的类型。所以,使用 Car 类创建 Car 对象。如果 Car 类继承 Vehicle 超类,则 Car 对象还将是一个 Vehicle 对象。这反映了我们在现实世界中分类事物的方法。但正如您将看到的,类型不仅仅是分类系统元素的有用方法。类型是面向对象编程的基础,因为类型是良好一致的行为的保证。许多设计技巧来自该保证。 “开始了解 PHP V5 中的对象”展示对象为您保证了接口。当系统传递 Dictionary 对象时,您可以确定它具有 $translations 数组和 summarize() 方法。相反,关联数组不提供相同级别的确定性。要利用类提供的清晰接口,需要知道您的对象实际上是 Dictionary 的一个实例,而不是某个 imposter。可以用 instanceof 操作符来手动验证这一点,该操作符是 PHP V5 引入的介于对象实例和类名之间的一个便捷工具。 $en instanceof Dictionary 如果给定对象是给定类的实例,则 instanceof 操作符解析为真。在调用方法中第一次遇到 Dictionary 对象时,可以在使用它之前检查它的类型。
if ( $en instanceof Dictionary ) { print $en->summarize();} 但是,如果使用 PHP V5 的话,可以将对象类型检查构建到类或方法声明中。 在“开始了解 PHP V5 中的对象”中,重点介绍两个类:Dictionary,它存储术语和翻译, DictionaryIO,它将 Dictionary 数据导出(导入)自(至)文件系统。这些特性使得将 Dictionary 文件发送到第三方翻译器变得容易,第三方翻译器可以使用自己的软件来编辑数据。然后,您可以重新导入已处理的文件。清单 1 是 Dictionary 类的一个版本,它接受一个 DictionaryIO 对象,并将其存储以备将来使用。 清单 1. 接受 DictionaryIO 对象的 Dictionary 类的一个版本
class Dictionary { public $translations = array(); public $type ="En"; public $dictio; function addDictionaryIO( $dictio ) { $this->dictio=$dictio; } function export() { if ( $this->dictio ) { $this->dictio->export( $this ); } }}class DictionaryIO { function export( $dict ) { print "exporting dictionary data "."($dict->type)\n"; }}$en = new Dictionary();$en->addDictionaryIO( new DictionaryIO() );$en->export();// output: // dumping dictionary data (En) DictionaryIO 类具有单个方法 export(),它接受一个 Dictionary 对象,并使用它来输出假消息。现在,Dictionary 具有两个新方法:addDictionaryIO(),接受并存储 DictionaryIO 对象; export(),使用已提供的对象导出 Dictionary 数据 —— 或者是在完全实现的版本中。 您可能会疑惑为什么 Dictionary 对象不仅实例化自己的 DictionaryIO 对象,或者甚至在内部处理导入导出操作,而根本不求助于第二个对象。一个原因是您可能希望一个 DictionaryIO 对象使用多个 Dictionary 对象,或者希望存储该对象的单独引用。另一个原因是通过将 DictionaryIO 对象传递给 Dictionary,可以利用类切换或 多态性。换句话说,可以将 DictionaryIO 子类(比如 XmlDictionaryIO)的实例传递给 Dictionary,并更改运行时保存和检索数据的方法。 图 1 显示了 Dictionary 和 DictionaryIO 类及其使用关系。
图 1. Dictionary 和 DictionaryIO 类 正如所显示的,没有什么阻止编码器将完全随机的对象传递给 addDictionaryIO()。只有在运行 export() 时,才会获得一个类似的错误,并发现已经存储在 $dictio 中的对象实际上并没有 export() 方法。使用 PHP V4 时,必须测试本例中的参数类型,以绝对确保编码器传递类型正确的对象。使用 PHP V5 时,可以部署参数提示来强制对象类型。只将所需的对象类型添加到方法声明的参数变量中,如清单 2 所示: 清单 2. 将对象类型添加到方法声明的参数变量中
function addDictionaryIO( DictionaryIO $dictio ) { $this->dictio=$dictio;}function export() { if ( $this->dictio ) { $this->dictio->export( $this ); }} 现在,如果客户机编码器试图将类型错误的对象传递给 addDictionaryIO(),PHP 引擎将抛出一个致命错误。因此,类型提示使得代码更安全。不幸的是,提示仅对对象有效,所以不能在参数列表中要求字符串或整数。必须手动测试这些原类型。 即使可以保证 addDictionaryIO() 将获得正确的对象类型,但不能保证该方法被首先调用。export() 方法测试 export() 方法中 $dictio 属性的存在,从而避免错误。但您可能希望更严格一些,要求 DictionaryIO 对象传递给构造函数,从而确保 $dictio 总是被填充。 调用覆盖方法 在清单 3 中,XmlDictionaryIO 集成 DictionaryIO。而 DictionaryIO 写入并读取序列化数据,XmlDictionaryIO 操作 XML,可以与第三方应用程序共享。XmlDictionaryIO 可以覆盖其父方法(import() 和 export()),也可以选择不提供自己的实现(path())。如果客户机调用 XmlDictionaryIO 对象中的 path() 方法,则在 DictionaryIO 中实现的 path() 方法被调用。 事实上,可以同时使用这两种方法。可以覆盖方法并调用父实现。为此,使用新关键字 parent。用范围解析操作符和所讨论方法的名称来使用 parent 。例如,假设需要 XmlDictionaryIO 使用当前工作目录(如果有一个可用)中叫做 xml 的目录;否则,它应使用由父 DictionaryIO 类生成的默认路径,如清单 3 所示: 清单 3. XmlDictionaryIO 使用 xml 目录或由 DictionaryIO 类生成的默认路径
class XmlDictionaryIO extends DictionaryIO { function path( Dictionary $dictionary, $ext ) { $sep = DIRECTORY_SEPARATOR; if ( is_dir( ".{$sep}xml" ) ) { return ".{$sep}xml{$sep}{$dictionary->getType()}.$ext"; } return parent::path( $dictionary, $ext ); }// ... 可以看到,该方法检查本地 xml 目录。如果该测试失败,则它使用 parent 关键字指派给父方法。 子类和构造函数方法 parent 关键字在构造函数方法中尤其重要。如果在子类中不定义构造函数,则 parent 构造函数代表您被显式调用。如果在子类中不创建构造函数方法。则调用父类的构造函数并传递任何参数是您的责任,如清单 4 所示: Listing 4. Invoking the parent class’s constructor
class SpecialDictionary extends Dictionary { function __construct( $type, DictionaryIO $dictio, $additional ) { // do something with $additional parent::__construct( $type, $dictio ); }}共3页。 1 2 3 :
领会暗示 首先介绍一下对象类型和类型提示的优点。一个类定义一种类型。从该类实例化的任何对象属于该类定义的类型。所以,使用 Car 类创建 Car 对象。如果 Car 类继承 Vehicle 超类,则 Car 对象还将是一个 Vehicle 对象。这反映了我们在现实世界中分类事物的方法。但正如您将看到的,类型不仅仅是分类系统元素的有用方法。类型是面向对象编程的基础,因为类型是良好一致的行为的保证。许多设计技巧来自该保证。 “开始了解 PHP V5 中的对象”展示对象为您保证了接口。当系统传递 Dictionary 对象时,您可以确定它具有 $translations 数组和 summarize() 方法。相反,关联数组不提供相同级别的确定性。要利用类提供的清晰接口,需要知道您的对象实际上是 Dictionary 的一个实例,而不是某个 imposter。可以用 instanceof 操作符来手动验证这一点,该操作符是 PHP V5 引入的介于对象实例和类名之间的一个便捷工具。 $en instanceof Dictionary 如果给定对象是给定类的实例,则 instanceof 操作符解析为真。在调用方法中第一次遇到 Dictionary 对象时,可以在使用它之前检查它的类型。
if ( $en instanceof Dictionary ) { print $en->summarize();} 但是,如果使用 PHP V5 的话,可以将对象类型检查构建到类或方法声明中。 在“开始了解 PHP V5 中的对象”中,重点介绍两个类:Dictionary,它存储术语和翻译, DictionaryIO,它将 Dictionary 数据导出(导入)自(至)文件系统。这些特性使得将 Dictionary 文件发送到第三方翻译器变得容易,第三方翻译器可以使用自己的软件来编辑数据。然后,您可以重新导入已处理的文件。清单 1 是 Dictionary 类的一个版本,它接受一个 DictionaryIO 对象,并将其存储以备将来使用。 清单 1. 接受 DictionaryIO 对象的 Dictionary 类的一个版本
class Dictionary { public $translations = array(); public $type ="En"; public $dictio; function addDictionaryIO( $dictio ) { $this->dictio=$dictio; } function export() { if ( $this->dictio ) { $this->dictio->export( $this ); } }}class DictionaryIO { function export( $dict ) { print "exporting dictionary data "."($dict->type)\n"; }}$en = new Dictionary();$en->addDictionaryIO( new DictionaryIO() );$en->export();// output: // dumping dictionary data (En) DictionaryIO 类具有单个方法 export(),它接受一个 Dictionary 对象,并使用它来输出假消息。现在,Dictionary 具有两个新方法:addDictionaryIO(),接受并存储 DictionaryIO 对象; export(),使用已提供的对象导出 Dictionary 数据 —— 或者是在完全实现的版本中。 您可能会疑惑为什么 Dictionary 对象不仅实例化自己的 DictionaryIO 对象,或者甚至在内部处理导入导出操作,而根本不求助于第二个对象。一个原因是您可能希望一个 DictionaryIO 对象使用多个 Dictionary 对象,或者希望存储该对象的单独引用。另一个原因是通过将 DictionaryIO 对象传递给 Dictionary,可以利用类切换或 多态性。换句话说,可以将 DictionaryIO 子类(比如 XmlDictionaryIO)的实例传递给 Dictionary,并更改运行时保存和检索数据的方法。 图 1 显示了 Dictionary 和 DictionaryIO 类及其使用关系。
图 1. Dictionary 和 DictionaryIO 类 正如所显示的,没有什么阻止编码器将完全随机的对象传递给 addDictionaryIO()。只有在运行 export() 时,才会获得一个类似的错误,并发现已经存储在 $dictio 中的对象实际上并没有 export() 方法。使用 PHP V4 时,必须测试本例中的参数类型,以绝对确保编码器传递类型正确的对象。使用 PHP V5 时,可以部署参数提示来强制对象类型。只将所需的对象类型添加到方法声明的参数变量中,如清单 2 所示: 清单 2. 将对象类型添加到方法声明的参数变量中
function addDictionaryIO( DictionaryIO $dictio ) { $this->dictio=$dictio;}function export() { if ( $this->dictio ) { $this->dictio->export( $this ); }} 现在,如果客户机编码器试图将类型错误的对象传递给 addDictionaryIO(),PHP 引擎将抛出一个致命错误。因此,类型提示使得代码更安全。不幸的是,提示仅对对象有效,所以不能在参数列表中要求字符串或整数。必须手动测试这些原类型。 即使可以保证 addDictionaryIO() 将获得正确的对象类型,但不能保证该方法被首先调用。export() 方法测试 export() 方法中 $dictio 属性的存在,从而避免错误。但您可能希望更严格一些,要求 DictionaryIO 对象传递给构造函数,从而确保 $dictio 总是被填充。 调用覆盖方法 在清单 3 中,XmlDictionaryIO 集成 DictionaryIO。而 DictionaryIO 写入并读取序列化数据,XmlDictionaryIO 操作 XML,可以与第三方应用程序共享。XmlDictionaryIO 可以覆盖其父方法(import() 和 export()),也可以选择不提供自己的实现(path())。如果客户机调用 XmlDictionaryIO 对象中的 path() 方法,则在 DictionaryIO 中实现的 path() 方法被调用。 事实上,可以同时使用这两种方法。可以覆盖方法并调用父实现。为此,使用新关键字 parent。用范围解析操作符和所讨论方法的名称来使用 parent 。例如,假设需要 XmlDictionaryIO 使用当前工作目录(如果有一个可用)中叫做 xml 的目录;否则,它应使用由父 DictionaryIO 类生成的默认路径,如清单 3 所示: 清单 3. XmlDictionaryIO 使用 xml 目录或由 DictionaryIO 类生成的默认路径
class XmlDictionaryIO extends DictionaryIO { function path( Dictionary $dictionary, $ext ) { $sep = DIRECTORY_SEPARATOR; if ( is_dir( ".{$sep}xml" ) ) { return ".{$sep}xml{$sep}{$dictionary->getType()}.$ext"; } return parent::path( $dictionary, $ext ); }// ... 可以看到,该方法检查本地 xml 目录。如果该测试失败,则它使用 parent 关键字指派给父方法。 子类和构造函数方法 parent 关键字在构造函数方法中尤其重要。如果在子类中不定义构造函数,则 parent 构造函数代表您被显式调用。如果在子类中不创建构造函数方法。则调用父类的构造函数并传递任何参数是您的责任,如清单 4 所示: Listing 4. Invoking the parent class’s constructor
class SpecialDictionary extends Dictionary { function __construct( $type, DictionaryIO $dictio, $additional ) { // do something with $additional parent::__construct( $type, $dictio ); }}共3页。 1 2 3 :
下载本文示例代码
高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究高级PHP V5 对象研究
阅读(171) | 评论(0) | 转发(0) |