Java - Defining a member that extends class A and implements interface B

前端 未结 2 832
悲哀的现实
悲哀的现实 2020-12-21 17:30

I have a variable that must meet two conditions, and I want to set them in the definition

I know that I can define either condition with an individual variable, like

相关标签:
2条回答
  • 2020-12-21 17:53

    While Java does not directly support intersection types like A&B, such types do appear in type parameter bounds and capture conversions. We can express A&B with a layer of abstraction.

    public class ValueAB<T extends A&B>
    {
        public final T v;
    
        // constructor ...
    }
    
    public class ClassAB<T extends A&B>
    {
        public final Class<T> clazz;
    
        // constructor ...
    }
    

    Instead of A&B, Class<? extends A&B>, we use wrappers ValueAB, ClassAB

        ClassAB<?> clazz = new ClassAB<>(Foo.class);   
    
        ValueAB<?> value = new ValueAB<>(clazz.c.newInstance());
    
        value.v.methodOfA();
        value.v.methodOfB();
    

    This solution would require a wrapper for each combination of As and Bs.


    Another solution is to use only A as type parameter bound; B will be supplied by wildcard bound. This is probably better if you need to express multiple A&B1, A&B2, ... types at use site.

    public class ValueA<T extends A>
    {
        public final T v;
        ...
    }
    
    
    public class ClassA<T extends A>
    {
        public final Class<T> c;
        ...
    }
    
    ---
    
        ClassA<? extends B> clazz = new ClassA<>(Foo.class);
    
        ValueA<? extends B> value = new ValueA<>(clazz.c.newInstance());
    

    If it's confusing how wildcard works in these cases, see my article on wildcard


    A 3rd solution is free of A or B at declaration site of wrappers; the use site provides A and B.

    public class Value<T extends S, S>
    {
        public final T v;
        ...
    }
    
    
    public class Clazz<T extends S, S>
    {
        public final Class<T> c;
        ...
    }
    
    ---
    
        Clazz<? extends A, B> clazz = new Clazz<>(Foo.class);
    
        Value<? extends A, B> value = new Value<>(clazz.c.newInstance());
    

    This is however probably too confusing.

    0 讨论(0)
  • 2020-12-21 17:58

    You can declare type parameters that have multiple bounds, such as:

    public static <T extends A & B> void test(Class<T> clazz)
    

    But you cannot declare a variable that has multiple bounds:

    private Class<? extends A & B> variable;  // doesn't work
    

    You can create an abstract class C that extends A and implements B, so that only one bound is required.

    abstract class C extends A implements B {}
    

    Then:

    private Class<? extends C> variable;
    
    0 讨论(0)
提交回复
热议问题