它是一种具有特征和同样命名的对象的好风格吗?

时间:2011-05-09 09:41:32

标签: scala

在我浏览Paul Phillips GitHub repositories时,我注意到他经常使用某种结构:

trait A {
 // ...
}
object A extends A

例如:scala-improving, strings 首先,从Java开始,我不知道同一范围内的特征和对象具有相同的名称 现在我问它有什么好处?与所有特征成员直接定义对象有什么好处?好吧,我知道这个特性可以混合在一起,但我假设在实践中只使用了这个对象。

3 个答案:

答案 0 :(得分:11)

至少有一种情况是这种模式派上用场的是当你构建一个函数库时。您可以重新组合函数(实际上是方法,但让它们在此上下文中将它们称为函数)为几个特征(可以将其视为模块),例如MyLibAMyLibB,{然后,如果对于它们中的每一个,你定义了一个实现它的对象,你的lib的用户可以通过编写来轻松地使用它,例如:

MyLibC

(假设import mypackage.MyLibA._ 是包含的包)。此外,您可以通过提供对象mypackage轻松提供导入lib的所有功能的方法,如下所示:

MyLib

然后用户只需导入object MyLib extends MyLibA with MyLibB with MyLibC ,而不是分别为每个模块编写导入。更好的是,您可以定义mypackage.MyLib._,然后用户只需编写package object mypackage extends MyLibA with MyLibB with MyLibC。并且,奖励是那些想要在一行中仅导入import mypackage._MyLibA的挑剔用户也可以自由定义他们自己的“导入对象”,甚至可能使用他们自己的实用程序功能完成它,或压倒你自己的:

MyLibB

...然后使用object UserLibImport extends MyLibA with MyLibB { def userAdditionalFunction = /* ... */ override def someRedefinedLibAFunction = /* ... */ }

导入所有内容

所以,我说,在这种情况下,不仅是好的风格,强烈建议以这种方式提供你的功能,因为它允许最大的灵活性。

(这也在this answer中进行了简要解释。)

答案 1 :(得分:3)

当您需要实用程序方法的全局单例时,object是一个显而易见的选择。与Java的静态不同,您可以将此对象作为特征的实例输入。

这里的一大优势是您可以创建该特征/接口的另一个实例以用于单元测试。如果你正在使用TDD / BDD,非常方便,在可测性方面,静力学通常是一个痛苦的问题。

答案 2 :(得分:0)

特质是可重复使用的。 Trait只定义了对象A的契约,可能是某种实现。但是这个特性可以用于模拟对象,如上所述,用于聚合功能。