伴侣对象具有实现接口的好处
为什么在Kotlin / Scala中,伴侣对象可以实现一些接口,这有什么好处呢? 何时使用此function是有用的?
因为companion object
是object
,所以object
可以实现接口(或者扩展类),特别是没有理由不允许它用于companion object
。
Scala中的一个常见用途是工厂:例如Seq
, List
, Vector
等。伴随对象都扩展了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
我们现在有两个类User
和Article
,表示数据库的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()