EnzoMolion
EnzoMolion

Reputation: 1047

Parameter a class with type A or B

I am trying to parameter a class with a type that is whether A or B and nothing else.

Something like

final class ChildClass<A | B> extends MotherClass {

This way I can create a ChildClass<A> or a ChildClass<B> but nothing else.

Is it possible in Java?


Edit:

I must specify that I am using Java 8 and that I have no control of classes A and B (which are classes of the Android framework I am working with).

Upvotes: 4

Views: 2752

Answers (4)

Eugene
Eugene

Reputation: 120988

With the addition of this JEP, there is a rather interesting way to do it now.

You can create an interface that is sealed:

sealed interface F permits A, B {

    default String name() {
        return "F";
    }
}

add the generic type that is going to be bounded by this interface:

static class WithGenerics<T extends F> {

    private final T t;

    public WithGenerics(T t) {
        this.t = t;
    }

    public void findName() {
        System.out.println(t.name());
    }

}

And finally create the two classes A and B:

static final class A implements F {
    .....
}

static final class B implements F {
   .....
}

And you have effectively said that only A and B can be passed to :

 WithGenerics<A> a = new WithGenerics<>(new A());
 a.findName();

 WithGenerics<B> b = new WithGenerics<>(new B());
 b.findName(); 

because there can be no type C that can potentially implement F.

Upvotes: 2

WJS
WJS

Reputation: 40047

This way I can create a ChildClass<A> or a ChildClass<B> but nothing else. Is it possible in Java?

I am assuming that A and B are real types and not just generic parameters. Otherwise, A and B could be anything so you may as well just have A.

So why not just predefine the class to return an instance of whichever ones are allowed?

class MyClass<A> extends MotherClass {
    private MyClass() {
    }
    
    public static MyClass<Integer> instanceOfInteger() {
        return new MyClass<Integer>();  
    }
    public static MyClass<String> instanceOfString() {
         return new MyClass<String>();
    }
    // rest of class here
}


MyClass<Integer> mc1 = MyClass.instanceOfInteger();
MyClass<String> mcs = MyClass.instanceOfString();

Upvotes: 1

HyperProgrammer
HyperProgrammer

Reputation: 204

You might be able to check the class type of T like this:

public Class Foo<T> extends MotherClass {
    private final Class<T> classType;

    public Foo(Class<T> classType) {
        this.classType = classType;
    }

    public Class<T> getClassType() {
        return this.classType;
    }

    public void method() {
        if (classType.equals(A.class)) {
        //Do something
        } else if (classType.equals(B.class)) {
        //Do something
        }
    }
}

Heres an example of creating an object of Foo..

Foo<A> foo = new Foo<>(A.class);

Hope this helps you if it doesn't leave a comment and I'll try to edit and provide a more helpful answer.

Upvotes: 1

Unfortunately is not. Search for term union types in java or java either type.

The most known case of union types in Java is catching multiple exceptions, which is built-in into language, however it would be awful to abuse exceptions for your own types.

Here is also interesting workaround.

Upvotes: 5

Related Questions