Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Union types in Java

I've been working with C# for a while and trying to get more familiar with Java. So I'm trying to migrate some of the basic patterns I use on daily basis in C# even only to understand the gap between JVM and dotnet and figure out how to deal with them. Here is the first problem I encountered - an option type - somethiong which is quite easy to achieve in many languages i.e. Koltlin:

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

so I can easily create a map functor:

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))} 

Is this something I can achieve in Java? Im not concerned about the lack of extentions methods, I can leave without that, but how to perform the actual type matching without having to rely on an unchecked cast? At least thats what IntelliJ is complaining about...

like image 345
Michal Pawluk Avatar asked Mar 26 '18 12:03

Michal Pawluk


People also ask

What is union type in Java?

(experimental) Union Types are abstract types that are similar to Interface Types, but they cannot to specify any common fields between types. Note that fields of a union type need to be object types. In other words, you can't create a union type out of interfaces, other unions, or inputs.

Are there unions in Java?

Since the Java programming language does not provide the union construct, you might think there's no danger of implementing a discriminated union. It is, however, possible to write code with many of the same disadvantages.

Is union a type?

A union is a special data type available in C that allows to store different data types in the same memory location. You can define a union with many members, but only one member can contain a value at any given time.

What are union types in TS?

A union type describes a value that can be one of several types. We use the vertical bar ( | ) to separate each type, so number | string | boolean is the type of a value that can be a number , a string , or a boolean .


1 Answers

in the specific case you mentioned, the following would work:

  • (as @oldcurmudgeon mentioned) java.util.Optional it also has a map function.
  • there's also the guava library, that has com.google.common.base.Optional, in case you want it for java version 7 and below. the equivalent of map here would be the transform function.

Java doesn't have pattern matching. The closest you can get to pattern matching in Java is with the visitor pattern.

usage:

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
    }
});

boilerplate 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);
    }
}
like image 113
Eric Avatar answered Sep 26 '22 13:09

Eric