关于OOP,有三种常见的方法AFAIK实现可重用性
- 继承:通常代表is-一种关系(鸭子is-鸟)
- 组成:通常代表有一个关系(汽车有一个引擎)
- 特性(例如PHP中的trait关键字):...对此不确定
虽然在我看来特质可以实现has-a和is-a关系,但我真的不确定它打算用于哪种建模。特征是针对哪种情况设计的?
关于OOP,有三种常见的方法AFAIK实现可重用性
虽然在我看来特质可以实现has-a和is-a关系,但我真的不确定它打算用于哪种建模。特征是针对哪种情况设计的?
Answers:
性格是作曲的另一种方式。可以将它们视为在编译时(或JIT编译时)组成类的所有部分的一种方法,以组装所需部分的具体实现。
基本上,当您发现自己制作具有不同功能组合的类时,便希望使用特征。这种情况最经常出现在人们编写灵活的库供他人使用的情况下。例如,这是我最近使用ScalaTest编写的单元测试类的声明:
class TestMyClass
extends WordSpecLike
with Matchers
with MyCustomTrait
with BeforeAndAfterAll
with BeforeAndAfterEach
with ScalaFutures
单元测试框架有一个吨的不同的配置选项,每一个团队都有关于他们如何想要做的事情不同的喜好。通过将选项放入特征(with
在Scala 中混合使用),ScalaTest可以提供所有这些选项,而无需创建类名(如WordSpecLikeWithMatchersAndFutures
)或创建大量运行时布尔标志(如)WordSpecLike(enableFutures, enableMatchers, ...)
。这使得遵循开放/封闭原则变得容易。您只需添加新特征即可添加新功能和功能的新组合。这也使遵循接口隔离原则变得更加容易,因为您可以轻松地将普遍不需要的功能放入特征中。
特性也是将通用代码放入几个类的共享共享继承层次结构的一种好方法。继承是一个紧密耦合的关系,如果可以帮助的话,您不应该为此付出代价。特质是一种松散耦合的关系。在上面的示例中,我曾经MyCustomTrait
在几个其他不相关的测试类之间轻松共享模拟数据库实现。
依赖注入实现了许多相同的目标,但是在运行时基于用户输入,而不是在编译时基于程序员输入。特性也更多地用于语义上属于同一类的依赖项。您是在组装一个班级的各个部分,而不是召集其他负责任的班级。
依赖项注入框架根据程序员的输入在编译时实现了许多相同的目标,但是对于没有适当特征支持的编程语言,很大程度上是一种变通方法。特性将这些依赖项以更简洁的语法和更简单的构建过程带入了编译器类型检查器的领域,从而使编译时依赖项和运行时依赖项之间的区别更加清晰。
with
运营商有什么区别他们,with
是一个复合操作。是的,特征可以替换DI,而无需在代码的入口点进行定义。在我看来,这是使它们更受欢迎的原因之一。