Gor*_*don 20
不,由于特征被"粘贴"到一个类中的规则完全不同,因此特征不仅仅是构成.
使用Composition时,不存在冲突或方法覆盖的可能性,因为复合元素是一个完全隔离的单元(某个其他类的实例),它通过它在消费实例中的公共API进行交互.此外,如果您需要从使用实例提供访问权限,则必须添加代理方法以委派给复合元素.
另一方面,特征成为它们所使用的实例的API的一部分.它们不是实例中的子系统.它们甚至不是实例,而只是一个可重复使用的样板代码.这提供的一个好处是满足与特征的接口,正如我在PHP中的Traits中所示- 任何真实世界的示例/最佳实践?
你必须要小心你给作曲的意义.在更一般的意义上,特征是分解和组合的机制.
特征是一种组合机制,因为它们可以由一个类组成.许多特征实现还允许特征彼此组合.
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(这是与状态的特征).(虽然这篇博客文章将其描述为无国籍)
总而言之,根据特征进行思考可能有助于编写更好的代码.编写特征类以避免实例化也可以有助于更好的代码.这可以从任何依赖项中释放特征,从而可以按任何顺序调用它们.但目前尚不清楚在语言本身中添加特征的概念会有助于提高代码质量.