Why in Kotlin/Scala companion objects can implements some interfaces, what benefits this can have? When is useful to use this feature?
You can use companion objects and inheritance for some level of class-lavel or static polymorphism.
Consider an interface
interface Factory<T> {
fun create(): T
}
Now, we create a class whose companion object implements it
class Foo {
companion object: Factory<Foo> {
override fun create() = Foo()
}
}
Now we can create an extension function for all factories to create and e.g. log the object.
fun <T> Factory<T>.createAndLog(): T {
val t = create()
println(t)
return t
}
Und use it like so
Foo.createAndLog()
Consider a marker interface
interface Queryable<T>
We now have two classes User and Article that represent tables in a database whose companion object implements the interface.
class User(val id: String) {
companion object: Queryable<User> {}
}
class Article(val authorId: String) {
companion object: : Queryable<Article> {}
}
We can now define an extension function to create a query from the class
fun <T> Queryable<T>.query() = db.createQuery<T>()
which we can call as
User.query()
//or
Article.query()
Because companion objects are objects, objects can implement interfaces (or extend classes), and there is no good reason to disallow it for companion objects in particular.
One common use in Scala is for factories: e.g. Seq, List, Vector etc. companion objects all extend TraversableFactory so you can write code working with a TraversableFactory and pass any of them to construct the type you want. E.g.
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)
Similarly, all case class companion objects extend function types.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With