特质不仅仅是构图吗?

nkr*_*1pt 21 php oop traits mixins

我正在阅读一篇关于PHP 5.4.0中的新功能的文章.最令人期待的一个是特质.

阅读这些特征,看看它们的全部内容,它们只是看起来像编译器辅助的复制粘贴给我; 和一种语言提供了使用组合的方式,非常类似于众所周知的战略模式中使用的,它利用了"有利于构成而不是继承"的设计原则.

我理解正确吗?

这些特性可以提供哪些其他优势,这使得它们有价值而不仅仅是使用构图设计原则?

Gor*_*don 20

不,由于特征被"粘贴"到一个类中的规则完全不同,因此特征不仅仅是构成.

使用Composition时,不存在冲突或方法覆盖的可能性,因为复合元素是一个完全隔离的单元(某个其他类的实例),它通过它在消费实例中的公共API进行交互.此外,如果您需要从使用实例提供访问权限,则必须添加代理方法以委派给复合元素.

另一方面,特征成为它们所使用的实例的API的一部分.它们不是实例中的子系统.它们甚至不是实例,而只是一个可重复使用的样板代码.这提供的一个好处是满足与特征的接口,正如我在PHP中的Traits中所示- 任何真实世界的示例/最佳实践?

  • 这不会使特征比仅仅将外部实例组成一个类更危险吗?与特征的代码块(方法?我不知道你在特征中称它们是什么)和宿主类方法的冲突怎么样?或者导入同一个类的多个特征的代码块之间是否存在冲突?也许我错过了一些东西,但在我看来,如果不仔细使用,特征会很快变得非常混乱. (2认同)

wid*_*ged 5

你必须要小心你给作曲的意义.在更一般的意义上,特征是分解和组合的机制.

  • 分解 - 我们如何将软件基础分解为合适的重用单元(代码重用,DRY).
  • 组合 - 我们如何组合这些单元以获得适合我们的应用程序域的类层次结构.

特征是一种组合机制,因为它们可以由一个类组成.许多特征实现还允许特征彼此组合.

GoF的口头禅是"赞成合成而非继承".

默认情况下,所有基于类的语言都支持继承.对象只能从其类或从其继承链中更高的类中获取行为.当然,你可以通过不同的方式获得相同的结果.例如,您可以创建一个Manager类(例如,LayoutMananager),然后在任何具有可铺设行为/布局特征的类中添加对它的引用,并添加除了调用Manager的方法之外什么都不做的函数

public function doSomething() { return layoutManager.doSomething(); }
Run Code Online (Sandbox Code Playgroud)

特质有利于作文.就那么简单.特征的关键特征是它们生活在类层次结构之外.您可以"获取"可重复使用的行为或特征,而不会来自您的任何超级类别(其他帖子中引入的水平与垂直区别).这是主要优势.

特征的最大问题是当特征以一种你可以直接执行myObject.doSomething()而不是myObject.trait1.doSometing()的方式实现冲突时出现冲突(直接或间接地如上所述使用layoutManager).一旦向类中添加多个特征,就很容易出现冲突.您的实现需要支持别名和覆盖等机制来帮助解决冲突.你得到了一些回报.

目前尚不清楚PHP实现是否符合这一点,但是traits也应该不指定任何实例变量,traits提供的方法永远不应该直接访问实例变量.(来源:将特征添加到(静态类型)语言,PDF).这篇博文讨论了这一点.它声称在PHP中,名为trait的结构确实是一个mixin(这是与状态的特征).(虽然这篇博客文章将其描述为无国籍)

总而言之,根据特征进行思考可能有助于编写更好的代码.编写特征类以避免实例化也可以有助于更好的代码.这可以从任何依赖项中释放特征,从而可以按任何顺序调用它们.但目前尚不清楚在语言本身中添加特征的概念会有助于提高代码质量.