Unit is a type (unlike void) and has a value (unlike Void). This enable uniform treatment of Unit when it comes to generic classes. I.e. we don’t need another two types: a function that returns something and a function that returns void. It’s all one type: a function that returns something tat may be Unit.
Introducing void would pose many problems in areas like type inference, compositionality of any sort of functions, etc
I’m not suggesting introducing void as a kotlin type, but rather annotating Unit for better Java interop. There is a straightforward translation from void to Unit which the compiler could do:
If void is covariant:
fun f(): @JvmVoid Unit {..}
would compile to two functions, one for kotlin, one for java:
public void f_kotlin(): Unit {
..
}
public void f_java() {
f_kotlin();
}
And if it’s contravariant the java version would just wrap void functions and pass in Unit.INSTANCE automatically.
This functionality is also required to maintain compatibility with code that inspects the return type of a method and will fail if it is not void. For example, in the Arquillian testing suite, the org.jboss.arquillian.junit.Arquillian.validatePublicVoidNoArgMethods() method checks to make sure that a test function annotated with @BeforeClass returns void. Without some way to generate the correct signature, Kotlin can’t be used with these libraries.
Better no.
Advise which is not like by kotlin itself:
If you want to be java-compatible, declare your lambdas using java-functional interfaces.
Kotlin has fun interfaces themselves, but I didn’t look into them yet
Might be a little to the party, I ended up using interfaces to solve this.
for one or two usages this is an overkill, bt if you find yourself return Unit.INSTANCE over and over again, do this:
define an interface for your callback as YourInerface
define your kotlin function with the callback argument being of type YourInerface
add an extension fun with the callback argument being of pure-kotlin-function type
Android Studio (and other IDEs) don’t auto-complete kotlin extensions in java files, so the kotlin variant is excluded from the auto-complete suggestions.
demo:
data class User(...)
// 1. interface
interface OnGotUser { fun onGotUser(user: User) }
class UserGetter {
// 2. fun with callback of type interface
fun retrieveUser(callback: OnGotUser){
val user: User = getUserUsingFancyStuff() // get it somehow
callback.onGotUser(user)
}
}
// 3. extension with callback of type pure-function
// if the Interface OnGotUser is defined in a java file, you can use SAM constructors and do this:
fun UserGetter.retrieveUser(callback: (User)->Unit)
= retrieveUser(OnGotUser { callback(it) })
// if the interface OnGotUser is defined in a kotlin file, it looks a little bit worse
// [see kotlin bug](https://discuss.kotlinlang.org/t/sam-conversion-on-kotlin-interfaces/1433):
fun UserGetter.retrieveUser(callback: (User)->Unit) =
retrieveUser(object: OnGotUser {
override fun onGotUser(user: User) = callback(user)
})