Max
Max

Reputation: 5081

Statically importing Kotlin Companion methods?

tl:dr; Is it possible to import a method inside a companion object of another class, without qualifying the import with Companion? That is, is there any possible way I can say import Bar.toFoo instead of import Bar.Companion.toFoo, assuming toFoo is a method on Bar's companion object?


We're migrating a class from Java to Kotlin. Our class looks like this:

class Bar {
  static Foo toFoo() {
    return new Foo();
  }
}

And then, to use it, from a class that happens to be Kotlin, we say something like:

import Bar.toFoo;

// ...
    Bar().convert(toFoo()); // like a Java 8 Collector
// ...

When we convert Bar to Kotlin, it looks like this:

class Bar {
  companion object {
    @JvmStatic fun toFoo() = Foo()
  }
}

We'd like the calling code to work without modification, however

import Bar.toFoo

no longer works, even with @JvmStatic! Instead, we have to update it to

import Bar.Companion.toFoo

which we'd rather not have to do -- we want to switch the Bar class to Kotlin without updating the callers.

Thoughts? We're using Kotlin 1.1.2-2.

Upvotes: 15

Views: 5595

Answers (1)

tango24
tango24

Reputation: 474

Unlike Java, Kotlin does not allow you to call static members via instance reference. Java dispatches these members based on the compile time declaration, so in

class Bar {
    static Foo toFoo() { return new Foo(); }
}

class Foo extends Bar {
    static Foo toFoo() { return new Foo(); }
}

class Baz {
    void test() {
        Bar fooAsBar = new Foo();
        Foo foo = fooAsBar.toFoo();
    }
}

In Java, fooAsBar.toFoo() will actually call Bar.toFoo() (the declared type) and not Foo.toFoo() (the runtime type). This is a source of misunderstanding and not good programming practice, so Kotlin does not support it.

However, you can define an extension function on Bar:

fun Bar?.toFoo() = Bar.toFoo()

Then you can call

val foo = fooAsBar.toFoo()

Upvotes: 4

Related Questions