3

Why in Kotlin/Scala companion objects can implements some interfaces, what benefits this can have? When is useful to use this feature?

Axel
  • 125
  • 1
  • 12
  • https://discuss.kotlinlang.org/t/what-is-the-advantage-of-companion-object-vs-static-keyword/4034 – Salem Dec 04 '17 at 10:19

3 Answers3

4

You can use companion objects and inheritance for some level of class-lavel or static polymorphism.

Example 1: Factories

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()

Example 2: Queries

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()
Kirill Rakhman
  • 42,195
  • 18
  • 124
  • 148
  • But why not to implement interfaces by classes themselves? – Axel Dec 04 '17 at 15:25
  • I'm calling the functions on the _class_, not an _instance_ of the class. As you can see from the last example, I never call the constructor of `User`or `Article`. – Kirill Rakhman Dec 04 '17 at 15:37
  • Yes, I see, but what benefits this have, to call functions on the _class_ and not on _instance_? – Axel Dec 04 '17 at 15:39
  • That's a very fundamental question. You could as well ask "Why do we need `companion object`s?" or "Why do we need `static` in Java?". I would recommend finding a satisfying answer to those questions before coming back to your original question. – Kirill Rakhman Dec 04 '17 at 15:50
  • I understand why we need companion object and static, mostly for namespacing, but why companion object need to implement some interface when class itself can implement interfaces, I don't get it. – Axel Dec 04 '17 at 16:00
3

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.

Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
1

You use singleton object when you need only one instance of particular class in program.

E.g. Scala's Nil implements List[Nothing]. Rather than every type of list to implement it's particular Nil there is just one of them.

In typeclass pattern, where you have just one implicit object for corresponding implementation.

Also, where you'd create a public static Something in Java, you'd create that in a companion object.

I personally found them useful for implementing an sbt plugin, that renders object Blah extends Renderable to files blah.html. Find more about usefulness here. I had to know that it implements that trait!

insan-e
  • 3,883
  • 3
  • 18
  • 43