在我浏览Paul Phillips GitHub repositories时,我注意到他经常使用某种结构:
trait A {
// ...
}
object A extends A
例如:scala-improving, strings 首先,从Java开始,我不知道同一范围内的特征和对象具有相同的名称 现在我问它有什么好处?与所有特征成员直接定义对象有什么好处?好吧,我知道这个特性可以混合在一起,但我假设在实践中只使用了这个对象。
答案 0 :(得分:11)
至少有一种情况是这种模式派上用场的是当你构建一个函数库时。您可以重新组合函数(实际上是方法,但让它们在此上下文中将它们称为函数)为几个特征(可以将其视为模块),例如MyLibA
,MyLibB
,{然后,如果对于它们中的每一个,你定义了一个实现它的对象,你的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的契约,可能是某种实现。但是这个特性可以用于模拟对象,如上所述,用于聚合功能。