0

0

高级PHP V5 对象研究

php中文网

php中文网

发布时间:2016-06-21 09:06:30

|

1047人浏览过

|

来源于php中文网

原创

对象|高级

高级php v5 对象研究
本文介绍了php v5一些更高级的面向设计的特性。其中包括各种对象类型,它们允许将系统中的组件相互分离,创建可重用、可扩展、可伸缩的代码。


  领会暗示 

  首先介绍一下对象类型和类型提示的优点。一个类定义一种类型。从该类实例化的任何对象属于该类定义的类型。所以,使用 car 类创建 car 对象。如果 car 类继承 vehicle 超类,则 car 对象还将是一个 vehicle 对象。这反映了我们在现实世界中分类事物的方法。但正如您将看到的,类型不仅仅是分类系统元素的有用方法。类型是面向对象编程的基础,因为类型是良好一致的行为的保证。许多设计技巧来自该保证。

  “开始了解 php v5 中的对象”展示对象为您保证了接口。当系统传递 dictionary 对象时,您可以确定它具有 $translations 数组和 summarize() 方法。相反,关联数组不提供相同级别的确定性。要利用类提供的清晰接口,需要知道您的对象实际上是 dictionary 的一个实例,而不是某个 imposter。可以用 instanceof 操作符来手动验证这一点,该操作符是 php v5 引入的介于对象实例和类名之间的一个便捷工具。

   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 类及其使用关系。

正如所显示的,没有什么阻止编码器将完全随机的对象传递给 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 );
 }
}

立即学习PHP免费学习笔记(深入)”;

  现在,如果客户机编码器试图将类型错误的对象传递给 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 类生成的默认路径

点触小程序平台源码.NETCORE版本
点触小程序平台源码.NETCORE版本

点触小程序是有南昌点触科技有限公司研发,我公司是国家级高新技术企业,本套源码是国内首家应该到目前为止也是独家用.netcore开发的小程序平台站,公司有三个开发组同时做小程序平台开发,一个php开发组,一个java开发组,一个.netcore开发组,三组独立并行开发。目前投入上线运营的未php版本,其他两组均是做封闭性开发测试,不对外公布。秉着互联网的合作,共享,开放,共赢的原则,我们将本套.NE

下载

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


抽象类和方法

  虽然在父类中提供默认行为是完全合法的,但这可能不是最巧妙的方法。对于启动器,您必须依赖子类的作者来理解它们必须实现 import() 和 export(),才能在 broken 状态创建类。而且,DictionaryIO 类实际上是兄弟,而不是父子。XmlDictionaryIO 不是 DictionaryIO 的特例;相反,它是一种备选实现。

  PHP V5 允许定义部分实现的类,其主要角色是为它的子女指定核心接口。这种类必须声明为抽象。


abstract class DictionaryIO {}


  抽象类不能实例化。必须创建子类(即,创建继承它的类),并创建该子类的实例。可以在抽象类中声明标准和抽象方法,如清单 5 所示。抽象方法必须用 abstract 关键字限定,且必须只由一个方法签名组成。这意味着,抽象方法应包括 abstract 关键字、可选的可见度修改符、function 关键字,以及圆括号内可选的参数列表。它们不应有任何方法主体。

  清单 5. 声明抽象类


abstract class DictionaryIO {

protected function path( Dictionary $dictionary, 
$ext ) {
$path = Dictionary::getSaveDirectory();
$path .= DIRECTORY_SEPARATOR;
$path .= $dictionary->getType().".$ext";
return $path;
}

abstract function import( Dictionary $dictionary ); 
abstract function export( Dictionary $dictionary ); 
}


  注意,path() 函数现在是受保护的。这允许来自子类的访问,但不允许来自 DictionaryIO 类型外部的访问。继承 DictionaryIO 的任何类必须实现 import() 和 export() 方法,否则就可能得到致命错误。

  声明抽象方法的任何类本身必须是声明为抽象的。继承抽象类的子类必须实现在其父类或自身中声明为抽象的所有抽象方法。

  清单 6 展示了具体的 DictionaryIO 类,为了简洁,此处省略了实际实现。

  清单 6. 具体的 DictionaryIO 类


class SerialDictionaryIO extends DictionaryIO {

 function export( Dictionary $dictionary ) {
  // implementation
 }

 function import( Dictionary $dictionary ) {
  // implementation
 }
}

class XmlDictionaryIO extends DictionaryIO {

 protected function path( Dictionary $dictionary, $ext ) {
  $path = strtolower(parent::path( $dictionary, $ext ) ); 
  return $path;
 }

 function export( Dictionary $dictionary ) {
  // implementation
 }

 function import( Dictionary $dictionary ) {
  // implementation
 }
}


  Dictionary 类需要一个 DictionaryIO 对象传递到它的构造函数,但它既不知道也不关心该对象是否是 XmlDictionaryIO 或 SerialDictionaryIO 的实例。它惟一知道的是给定对象继承 DictionaryIO,而且因此可以保证支持 import() 和 export() 方法。这种在运行时的类切换是面向对象编程的一个常见特性,称为多态性。

  图 2 展示了 DictionaryIO 类。注意,抽象类和抽象方法用斜体表示。该图是多态性的一个好例子。它展示了 DictionaryIO 类的已定义关系是与 DictionaryIO,但 SerialDictionaryIO 或 XmlDictionaryIO 将实现该关系。


图 2. 抽象 DictionaryIO 类及其具体子类 


接口

  与 Java? 编程语言应用程序一样,PHP 只支持单一继承。这意味着,类只可以继承一个父类(虽然它可能间接地继承许多祖先)。虽然这保证了清洁设计(clean design),但有时候您可能需要为一个类定义多个能力集。

  使用对象的一个优点是类型可以为您提供功能的保证。Dictionary 对象总是具有 get() 方法,而不管它是 Dictionary 本身还是其子类的实例。Dictionary 的另一个特性是它对 export() 的支持。假设需要让系统中的大量其他类同样地可导出。当想要将系统的状态保存到文件中时,可以为这些完全不同的类提供各自的 export() 方法,然后聚集实例,循环通过所有实例,并为每个实例调用 export()。清单 7 展示了实现 export() 方法的第二个类。

清单 7. 实现 export() 方法的第二个类


class ThirdPartyNews {
// ... 


class OurNews extends ThirdPartyNews { 
// ...
function export() {
print "OurNews export\n";
}
}


  注意,本例包括约束,即新类 OurNews 继承一个叫做 ThirdPartyNews 的外部类。

  清单 8 展示了聚集用 export() 方法装备的类实例的类。

  清单 8. 聚集用 export() 方法装备的类实例的类


class Exporter {
 private $exportable = array();
 function add( $obj ) {
  $this->exportable[] = $obj;
 }

 function exportAll() {
  foreach ( $this->exportable as $obj ) {
   $obj->export();
  }
 }
}


  Exporter 类定义了两个方法:add(),接受要存储的对象,和 exportAll(),循环通过已存储对象,以对每个对象调用 export()。这种设计的缺点显而易见:add() 不检查所提供对象的类型,所以 exportAll() 在轻快地调用 export() 时冒了致命的风险。 此处真正有用的是 add() 方法签名中的一些类型提示。Dictionary 和 OurNews 专用于不同的根。您可以依赖 add() 方法内部的类型检查,但这并不优雅而且不固定。每次创建支持 export() 的新类型时,就需要创建一个新类型检查。

  接口免去了这种麻烦。正如名称所表明的,接口定义功能而非实现。用 interface 关键字声明接口。


interface Exportable {
public function export();
}


  对于抽象类,可以定义任意数目的方法签名。子类必须提供每个方法的实现。但是,与抽象类不同,接口完全不能包含任何具体方法(也就是说,任何方法的任何特性都不能与其签名分离)。 类用 implements 关键字实现接口,如清单 9 所示。

  清单 9. 用 implements 关键字实现接口的类


class OurNews extends ThirdPartyNews 
implements Exportable {
 // ...
 function export() {
  print "OurNews export\n";
 }
}

class Dictionary implements Exportable, Iterator {
 function export() {
  //...
 }
}


  通过在 implements 后使用逗号分隔的列表,可以实现任意多的接口。必须实现每个接口中声明的所有方法,或者声明您的实现类抽象。 这样做可以得到什么呢?现在,Dictionary 和 OurNews 对象共享类型。所有此类对象还是 Exportable。可以用类型提示和 instanceof 测试来检查它们。清单 10 展示了修改后的 Exporter::add() 方法。

  清单 10. 修改后的 Exporter::add() 方法


class Exporter {
 private $exportable = array();
 function add( Exportable $obj ) {
  $this->exportable[] = $obj;
 }
//...


  接口是一个难以掌握的概念。毕竟,它们实际上并不提供任何有用代码。窍门是记住面向对象编程中类型的重要性。接口与合同类似。它借给类一个将类放置到位的名称,反过来,该类保证特定方法将可用。此外,使用 Exportable 对象的类既不知道也不关心调用 export() 时发生的行为。它只知道它可以安全地调用该方法。

  图 3 显示了 Exportable 接口与其实现类之间的关系。注意到 Exporter 与 Exportable 接口而非具体实现有使用关系。接口关系用虚线和开箭头表示。

结束语
  本文支持使用 PHP V5 中类型的价值。对象类型允许将系统中的组件相互分离,从而得到可重用、可扩展和可伸缩的代码。抽象类和接口帮助您基于类类型设计系统。 客户机类可被编码为只需要抽象类型,而把实现策略和结果留给在运行时传递给它们的具体类实例。也就是说,Dictionary 既不局限于序列化数据,也不局限于 XML。如果必须支持一种新格式,Dictionary 将不需要任何进一步的开发。它与保存数据以及从文件系统加载数据和将数据加载到文件系统的机制完全无关。Dictionary 只知道它必须具有一个 DictionaryIO 对象,从而保证 export() 和 import() 的功能。
  如果类保证了接口,您必须能够保证类。虽然 instanceof 功能提供了一种检查类型的好方法,但您还可以通过在参数列表中使用类型提示,来将对象类型检查滚动到方法签名自身中



PHP速学教程(入门到精通)
PHP速学教程(入门到精通)

PHP怎么学习?PHP怎么入门?PHP在哪学?PHP怎么学才快?不用担心,这里为大家提供了PHP速学教程(入门到精通),有需要的小伙伴保存下载就能学习啦!

下载

本站声明:本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热门AI工具

更多
DeepSeek
DeepSeek

幻方量化公司旗下的开源大模型平台

豆包大模型
豆包大模型

字节跳动自主研发的一系列大型语言模型

通义千问
通义千问

阿里巴巴推出的全能AI助手

腾讯元宝
腾讯元宝

腾讯混元平台推出的AI助手

文心一言
文心一言

文心一言是百度开发的AI聊天机器人,通过对话可以生成各种形式的内容。

讯飞写作
讯飞写作

基于讯飞星火大模型的AI写作工具,可以快速生成新闻稿件、品宣文案、工作总结、心得体会等各种文文稿

即梦AI
即梦AI

一站式AI创作平台,免费AI图片和视频生成。

ChatGPT
ChatGPT

最最强大的AI聊天机器人程序,ChatGPT不单是聊天机器人,还能进行撰写邮件、视频脚本、文案、翻译、代码等任务。

相关专题

更多
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法
pixiv网页版官网登录与阅读指南_pixiv官网直达入口与在线访问方法

本专题系统整理pixiv网页版官网入口及登录访问方式,涵盖官网登录页面直达路径、在线阅读入口及快速进入方法说明,帮助用户高效找到pixiv官方网站,实现便捷、安全的网页端浏览与账号登录体验。

286

2026.02.13

微博网页版主页入口与登录指南_官方网页端快速访问方法
微博网页版主页入口与登录指南_官方网页端快速访问方法

本专题系统整理微博网页版官方入口及网页端登录方式,涵盖首页直达地址、账号登录流程与常见访问问题说明,帮助用户快速找到微博官网主页,实现便捷、安全的网页端登录与内容浏览体验。

126

2026.02.13

Flutter跨平台开发与状态管理实战
Flutter跨平台开发与状态管理实战

本专题围绕Flutter框架展开,系统讲解跨平台UI构建原理与状态管理方案。内容涵盖Widget生命周期、路由管理、Provider与Bloc状态管理模式、网络请求封装及性能优化技巧。通过实战项目演示,帮助开发者构建流畅、可维护的跨平台移动应用。

42

2026.02.13

TypeScript工程化开发与Vite构建优化实践
TypeScript工程化开发与Vite构建优化实践

本专题面向前端开发者,深入讲解 TypeScript 类型系统与大型项目结构设计方法,并结合 Vite 构建工具优化前端工程化流程。内容包括模块化设计、类型声明管理、代码分割、热更新原理以及构建性能调优。通过完整项目示例,帮助开发者提升代码可维护性与开发效率。

19

2026.02.13

Redis高可用架构与分布式缓存实战
Redis高可用架构与分布式缓存实战

本专题围绕 Redis 在高并发系统中的应用展开,系统讲解主从复制、哨兵机制、Cluster 集群模式及数据分片原理。内容涵盖缓存穿透与雪崩解决方案、分布式锁实现、热点数据优化及持久化策略。通过真实业务场景演示,帮助开发者构建高可用、可扩展的分布式缓存系统。

23

2026.02.13

c语言 数据类型
c语言 数据类型

本专题整合了c语言数据类型相关内容,阅读专题下面的文章了解更多详细内容。

29

2026.02.12

雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法
雨课堂网页版登录入口与使用指南_官方在线教学平台访问方法

本专题系统整理雨课堂网页版官方入口及在线登录方式,涵盖账号登录流程、官方直连入口及平台访问方法说明,帮助师生用户快速进入雨课堂在线教学平台,实现便捷、高效的课程学习与教学管理体验。

14

2026.02.12

豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法
豆包AI网页版入口与智能创作指南_官方在线写作与图片生成使用方法

本专题汇总豆包AI官方网页版入口及在线使用方式,涵盖智能写作工具、图片生成体验入口和官网登录方法,帮助用户快速直达豆包AI平台,高效完成文本创作与AI生图任务,实现便捷智能创作体验。

421

2026.02.12

PostgreSQL性能优化与索引调优实战
PostgreSQL性能优化与索引调优实战

本专题面向后端开发与数据库工程师,深入讲解 PostgreSQL 查询优化原理与索引机制。内容包括执行计划分析、常见索引类型对比、慢查询优化策略、事务隔离级别以及高并发场景下的性能调优技巧。通过实战案例解析,帮助开发者提升数据库响应速度与系统稳定性。

51

2026.02.12

热门下载

更多
网站特效
/
网站源码
/
网站素材
/
前端模板

精品课程

更多
相关推荐
/
热门推荐
/
最新课程
前端系列快速入门课程
前端系列快速入门课程

共4课时 | 0.4万人学习

关于我们 免责申明 举报中心 意见反馈 讲师合作 广告合作 最新更新
php中文网:公益在线php培训,帮助PHP学习者快速成长!
关注服务号 技术交流群
PHP中文网订阅号
每天精选资源文章推送

Copyright 2014-2026 https://www.php.cn/ All Rights Reserved | php.cn | 湘ICP备2023035733号