web-dev-qa-db-ja.com

Javaのユニオンタイプ

私はしばらくC#で作業しており、Javaに慣れるために努力しています。したがって、JVMとdotnetの間のギャップを理解し、それらの処理方法を理解するためだけに、C#で日常的に使用するいくつかの基本パターンを移行しようとしています。これが私が遭遇した最初の問題です-オプションタイプ-多くの言語で達成するのが非常に簡単なサムチオング、つまりコルトリン:

sealed class Option<out T : Any> {
    object None : Option<Nothing>()
    data class Some<out T : Any>(val value: T) : Option<T>()}

簡単にマップファンクタを作成できます。

fun <T : Any, B : Any> Option<T>.map(f: (T) -> B): Option<B> =
    when (this) {
        is Option.None -> Option.None
        is Option.Some -> Option.Some(f(this.value))} 

これはJavaで実現できることですか?拡張メソッドの欠如を心配していませんが、それがなくてもかまいませんが、チェックされていないキャストに依存せずに実際の型マッチングを実行するにはどうすればよいですか?少なくともIntelliJが不満を言っているのは...

8
Michal Pawluk

あなたが言及した特定のケースでは、以下が機能します:

Javaにはパターンマッチングがありません。 Javaは ビジターパターン でパターンマッチングに到達できる最も近いものです。

使用法:

UnionType unionType = new TypeA();

Integer count = unionType.when(new UnionType.Cases<Integer>() {
    @Override
    public Integer is(TypeA typeA) {
        // TypeA-specific handling code
    }

    @Override
    public Integer is(TypeB typeB) {
        // TypeB-specific handling code
    }
});

ボイラープレートコード:

interface UnionType {
    <R> R when(Cases<R> c);

    interface Cases<R> {
        R is(TypeA typeA);

        R is(TypeB typeB);
    }
}

class TypeA implements UnionType {

    // ... TypeA-specific code ...

    @Override
    public <R> R when(Cases<R> cases) {
        return cases.is(this);
    }
}

class TypeB implements UnionType {

    // ... TypeB-specific code ...

    @Override
    public <R> R when(Cases<R> cases) {
        return cases.is(this);
    }
}
6
Eric