伴侣对象具有实现接口的好处

为什么在Kotlin / Scala中,伴侣对象可以实现一些接口,这有什么好处呢? 何时使用此function是有用的?

因为companion objectobject ,所以object可以实现接口(或者扩展类),特别是没有理由不允许它用于companion object

Scala中的一个常见用途是工厂:例如SeqListVector等。伴随对象都扩展了TraversableFactory因此您可以编写使用TraversableFactory代码并传递它们来构建所需的types。 例如

 def build[CC[X] <: Traversable[X] with GenericTraversableTemplate[X, CC], A](factory: TraversableFactory[CC])(elems: A*) = factory(elems) // build(List)(1,2,3) == List(1, 2, 3) // build(Set)(1,2,3) == Set(1, 2, 3) 

同样,所有的case类伴侣对象都扩展了函数types。

在程序中只需要一个特定类的实例时,就使用单例对象。

例如Scala的Nil实现List[Nothing] 。 而不是每种types的清单来实现它是特殊的 Nil ,只有其中之一。

在typeclass模式中 ,只有一个implicit object用于相应的实现。

另外,在Java中创建一个public static Something的地方,你可以在同伴对象中创建它。

我个人发现它们对于实现一个sbt插件很有用,它使得object Blah extends Renderable到文件blah.html 。 在这里find更多有用的信息 。 我必须知道它实现了这个特点!

您可以使用companion object和inheritance来实现一些层级或静态多态性。

例1:工厂

考虑一个接口

 interface Factory { fun create(): T } 

现在,我们创建一个伴侣对象实现它的类

 class Foo { companion object: Factory { override fun create() = Foo() } } 

现在我们可以为所有工厂创建一个扩展函数来创建和记录对象。

 fun  Factory.createAndLog(): T { val t = create() println(t) return t } 

不要像这样使用它

 Foo.createAndLog() 

例2:查询

考虑一个标记界面

 interface Queryable 

我们现在有两个类UserArticle ,表示数据库的companion object实现接口的表。

 class User(val id: String) { companion object: Queryable {} } class Article(val authorId: String) { companion object: : Queryable
{} }

我们现在可以定义一个扩展函数来从类中创建一个查询

 fun  Queryable.query() = db.createQuery() 

我们可以称之为

 User.query() //or Article.query()