It would be easier in your case to have the interface in Java:
fun createFoo() : Foo = Foo { "hello $it" }
But as you have a Kotlin interface instead, you are a bit out of luck here. Here is a related issue regarding this: KT-7770
A workaround to this could be (but that mainly depends on how you use that interface) to have a Kotlin interface as follows in place that is the main entry point for the Java side:
interface Foo : (String) -> String
On the Kotlin side you will not use it and the Java side should only use it to deliver functions, e.g.
// Java class
public class JFooFactory implements FooFactory {
@Override
@NotNull
public Foo createFoo() { // uses the Foo-interface from Kotlin
return input -> "hello " + input;
}
}
// Kotlin equivalent:
class KFactory : FooFactory {
override fun createFoo() : (String) -> String = {
"hello $it"
}
}
where the corresponding FooFactory
-interface could look like:
interface FooFactory {
fun createFoo() : (String) -> String
}
Usage could look like:
listOf(KFooFactory(), JFooFactory())
.map {
it.createFoo()
}
.forEach { func : (String) -> String -> // i.e. func is of (sub)type (String) -> String
func("demo") // calling it to deliver "hello demo" twice
}
Alternatively, to have also that Foo
-feeling for Kotlin you can do it as follows:
typealias Foo = (String) -> String
interface JFoo : Foo
// or if you put the interface in its own package you could also use:
interface Foo : someother.package.Foo
then the Java code stays the same as above, either with JFoo
or with Foo
pointing to that other package; the typealias is not visible from Java. The Kotlin side would change to the following:
class KFactory : FooFactory {
override fun createFoo() : Foo = {
"hello $it"
}
}
The Factory
-interface could also be replaced:
interface FooFactory {
fun createFoo() : Foo
}
Under the hood however everything stays the same. We have/use (String) -> String
in Kotlin and Foo
-functional-interface in Java.