关闭

类的继承、类的组合与 PHP 的 traits 特性

标签: 继承组合多态trait
1436人阅读 评论(0) 收藏 举报
分类:
面向对象的优势在于类的复用,继承与多态都是对类进行复用,继承是类级别的复用,多态是方法级别的复用。提到类的继承就必须提到类的组合,继承和组合有何异同?PHP到底有没有多态?这些将在下面进行讲述。

1. 类的继承
类与类之间有一种父与子的关系,子类继承父类的属性和方法,称为继承。在继承里,子类可以拥有父类的属性(除私有属性之外),也可以拥有父类的方法(除私有方法之外),同时,子类还可以有自己的属性和方法,并可以对继承的父类的方法进行重写。
PHP中,类的继承是一种单继承,也就是说一个子类只能有一个父类,但一个父类可以有多个子类。

2. 类的组合
如果我们把一个的类的对象,作为另外一个类的属性的值,这种代码的复用方式就叫做类的组合。

组合与继承都是提高代码可重用性的手段。在实际编程中,我们可以依据“低耦合”的标准,来选择应该使用组合还是继承。

耦合是对一个应用内不同模块(或层次)之间互连程度的度量,也就是不同模块之间的依赖关系。依赖程度越低,耦合度就越低。

低耦合是指模块之间的依赖关系较低,应尽可能地使模块间独立存在,以便实现解耦,也就是解除模块与模块之间的依赖。

按照这个思想,在组合和继承均可使用的情况下,更倾向于使用组合。因为继承有以下缺点:
  • 继承破坏类的封装性
  • 继承是紧耦合的
当然,组合也有缺点,在创建组合对象时,组合需要逐一创建局部对象,这在一定程度上增加了代码量,而继承则不需要这一步,因为子类会继承父类的方法。

虽然组合比继承增加了代码量,但总体来说,组合的优点大于缺点。继承最大的优点是扩展简单,但其缺点大于优点。因此,在代码设计时,需要慎重考虑。

对于专门用于被继承的类,继承树的抽象层应比较稳定,一般不要多于三层;对于不是专门用于被继承的类,可以禁止其被继承,也就是使用 final 关键字进行修饰。

子类扩展,而不是覆盖或者使父类的功能失效。优先考虑使用组合关系提高代码的可重用性。

底层代码多用组合,顶层(或业务层)代码多用继承。底层用组合可以降低耦合性,提高灵活性,避免对象臃肿;顶层用继承可以简化代码,让业务实现更方便。

那么,如果既要组合的灵活,又要继承的代码简洁,能做到吗?

这是可以做到的,譬如C++中的多重继承,就具有这个特性。多重继承中,一个子类可以同时继承多个父类,从而组合两个父类的功能。但多重继承过于灵活,会使模型变得复杂,造成“菱形问题”,故大多数语言都放弃了多重继承这一模型。

3. traits 特性
PHP本身是单继承的,但自PHP5.4引入了一种新的语法结构 traits。使用trait,可以方便地对类进行扩展,它是除extend、implements 外的另一种扩展对象的方式。trait 既可以使单继承模式的语言具备多继承的灵活性,又可以避免多继承带来的种种问题。

trait是为单继承语言而准备的一种代码复用机制,它减少了单继承语言的限制,使开发人员能够自由的在不同层次中对类的方法进行组合。

trait和class的结构类似,但它仅仅旨在用细粒度的方式来组合类的功能。trait不能通过它自身来实例化对象,它为传统的继承增加了水平方向的组合特性。

trait中可以定义属性和方法,在某个trait中可以使用其他的多个trait,在某个类中也可以使用多个trait。但如果trait中定义了某个属性,使用了该trait的类中,就不能定义同名的属性。

trait 的优先级
使用了trait的当前类的方法会覆盖trait中的同名方法,trait中的方法会覆盖被继承的父类中的同名方法。
也就是说,如果一个子类继承了父类,同时在子类中使用了trait,实例化子类后,调用子类的某个方法,会优先在子类中寻找是否有该方法,如果没有,就到trait中寻找该方法,如果还没有,就再到父类中寻找该方法。

关于trait的更多详细说明,请参考php的官方手册。

4. 多态
多态,顾名思义,就是多种状态多种结果。

以 C++ 为例,C++是强类型语言,变量、函数的参数、函数的返回值都是有状态的,也就是说必须指定变量的类型、参数的类型和返回值的类型。
C++中的多态是指调用同一个对象的同名方法时,由于传入的参数的类型(整型、浮点型、字符型等)的不同,而得到不同的结果。一个类中,可以有多个同名方法,同名方法的参数个数相同,但参数的类型却不相同。

从这种意义上来说,PHP中是没有多态的。因为PHP是弱类型语言,同一个类中是不允许存在同名方法的。

1
0
查看评论
发表评论
* 以上用户言论只代表其个人观点,不代表CSDN网站的观点或立场

PHP中的traits之二(trait继承中的优先级)

讲到trait,在此我不得不提一下trait中的优先级:        在trait继承中,优先顺序依次是:来自当前类的成员覆盖了 trait 的方法,而 trait 则覆盖了被继承的方法。   ...
  • tashanhongye
  • tashanhongye
  • 2015-08-20 12:00
  • 1304

PHP实现代码复用神器:trait

声明:这是自PHP 5.4.0起,PHP实现的代码复用的新特性,称为traits,如果你现在用的版本比5.4.0低的话,请升级!简单介绍:Traits 是一种为类似 PHP 的单继承语言而准备的代码复...
  • baidu_30000217
  • baidu_30000217
  • 2016-06-13 12:51
  • 893

PHP接口继承及接口多继承详解

在PHP的接口中,接口可以继承接口。虽然PHP类只能继承一个父类(单继承),但是接口和类不同,接口可以实现多继承,可以继承一个或者多个接口。当然接口的继承也是使用extends关键字,要多个继承的话只...
  • zyu67
  • zyu67
  • 2014-12-20 11:33
  • 5317

php面向对象开发之——组合模式

这个模式理解起来会有些歧义,特别是某些书上面那些难懂的阐述。先来说说组合模式的几个特点: 1、必须存在不可分割基本元素。 2、组合后的物体可以被组合。 举个通俗的例子,原子是化学反应...
  • phenixsoul
  • phenixsoul
  • 2013-01-08 16:14
  • 3292

PHP实现多种类型的排列组合算法

  • 2015-11-05 16:39
  • 2KB
  • 下载

PHP接口继承及接口多继承详解

在PHP的接口中,接口可以继承接口。虽然PHP类只能继承一个父类(单继承),但是接口和类不同,接口可以实现多继承,可以继承一个或者多个接口。当然接口的继承也是使用extends关键字,要多个继承的话只...
  • zyu67
  • zyu67
  • 2014-12-20 11:33
  • 5317

PHP中继承的特点和规则总结

在学习继承的过程中,感觉学习的比较乱,但是,最后学习下来,感觉也不是太乱,主要就是修饰符的访问权限问题,这里根据我的理解,觉得不太适合用表格来表示显示出来,那么我把在继承的特点来总结出来,便于记忆和理...
  • MyCodeDream
  • MyCodeDream
  • 2015-02-23 18:25
  • 2184

php类的封装、继承和多态的简单理解

面象对向的三大特点:封装性、继承性、多态性 首先简单理解一下抽象: 我们在前面定义一个类的时候,实际上就是把一类事物共有的属性和行为提取出来,形成一个物理模型(模版),这种研究问题的方法称为抽象 ...
  • u010817136
  • u010817136
  • 2015-04-21 11:51
  • 3970

[代码重用]--PHP 实现代码复用的一个方法 traits新特性

在阅读yii2源码的时候接触到了trait,就学习了一下,写下博客记录一下。自 PHP 5.4.0 起,PHP 实现了代码复用的一个方法,称为 traits。Traits 是一种为类似 PHP 的单继...
  • lhorse003
  • lhorse003
  • 2017-02-14 07:25
  • 110

PHP 实现代码复用的一个方法 traits新特性

这篇文章主要介绍了PHP 实现代码复用的一个方法,traits的新特性的相关资料,需要的朋友可以参考下 在阅读yii2源码的时候接触到了trait,就学习了一下,写下博客记录一下...
  • sanbingyutuoniao123
  • sanbingyutuoniao123
  • 2016-05-04 17:03
  • 126
    个人资料
    • 访问:274937次
    • 积分:4954
    • 等级:
    • 排名:第6654名
    • 原创:232篇
    • 转载:0篇
    • 译文:0篇
    • 评论:38条
    博客专栏
    最新评论