Kotlin Unit の特徴をまとめてみた

Unitは、Kotlinで最も頻繁に使用される型の一つでありながら、その存在感は意外と薄いものです。
JavaからKotlinに移行した多くのプログラマーにとって、KotlinがJavaのvoid型ではなく、新たにUnitという概念を導入した理由は疑問に思えるかもしれません。
実際には、Unitを完全に理解していなくても、Kotlinの開発を問題なく進めることは可能です。
しかし、UnitはKotlinの文法設計と密接に関係しており、Kotlin開発において静かに重要な役割を果たしています。
Unit とは
Unit を理解する最も直接的な方法は、ソースコードを読むことです。
package kotlin
/**
* The type with only one value: the `Unit` object. This type corresponds
* to the `void` type in Java.
*/
public object Unit {
override fun toString() = "kotlin.Unit"
}これはUnitのソースコードです。
ソースコードから分かるように、UnitはKotlinのクラスであり、またはSingleton Objectです。
Unit の用途
Unitは公式に定義された概念であり、何の値も返す必要がない場合の戻り値として使用されて、関数が意味のある値を返さないことを示します。
Javaのvoidに似ています。
Unit と void
Kotlinには本当に値を返さない関数が存在しません。
見た目上戻り値なしの関数の戻り値の型、実際にはUnitです。
見た目上戻り値なしように見えるのは、Kotlinが省略された部分を自動的に補完してくれるためです。
例えば、以下の2つのコードは完全に同じであり、戻り値の型としてのUnitと戻り値のUnitオブジェクトは省略できます:
fun main() {
println("Hello world!")
}
fun main(): Unit {
println("Hello world!")
return Unit
}これがKotlinのUnitとJavaのvoidの本質的な違いです。
なぜこのように設計されているのですか?
このように設計されたメリットは、voidを特別に扱う必要がないことです。
例えば、Javaコードは次のようになります。
abstract class Base<T> {
public abstract T make();
}
class Impl extends Base<Result> {
@Override
public Result make() {
return new Result();
}
}以下のような、Baseを継承したNilクラスの場合、makeメソッドでは「何の値も返す必要がない」ですが、継承とGenericsの制限のために、voidとは異なるVoidを導入する必要があり、Voidクラスとreturn nullを使用して実装されます。
class Nil extends Base<Void> {
@Override
public Void make() {
return null;
}
}一方、Kotlinでは、通常の関数と同じ方法で処理され、追加の概念を導入する必要がなくなります。
internal class Nil : Base<Unit>() {
override fun make() {}
}同様に、この方法は関数式にも適用できます。
fun run(block: () -> Any) { TODO() }
run { "String" } // () -> String
run { 0 } // () -> Int
run {} // () -> UnitEverything is an Expression
PythonやScalaなどの言語と同じ、Kotlin言語は「Everything is an Expression(一切皆有返回值)」というデザイン理念に基づいています。
これは、Kotlinがvoid型の特殊性を排除する根本的な理由でもあります。
「Everything is an Expression」という設計理念は、void以外にも適用されているところがあります、例えば:
- 戻り値はある
if-else文
fun run(flag: Boolean) {
val value = if (flag) "Kotlin" else "Java"
println("Hello $value!")
}
fun run(flag: Int) {
val value = if (flag == 0) {
"Kotlin"
} else if (flag > 0) {
"Java"
} else {
"?"
}
println("Hello $value!")
}- 戻り値がある
when expression
fun run(flag: Boolean) {
val value = when(flag) {
true -> "Kotlin"
else -> "Java"
}
println("Hello $value!")
}
fun run(flag: Int) {
val value = when {
flag == 0 -> "Kotlin"
flag > 0 -> "Java"
else -> "?"
}
println("Hello $value!")
}まとめ
Kotlinでは、Unit型が重要な役割を果たしており、関数が意味のある値を返さないことを示しています。Unit型を一貫して使用することで、Kotlinはvoidの特別性を排除し、関数シグネチャをより統一し、コードをより簡潔に明確にします。



