多种通用类型

时间:2019-05-29 18:06:46

标签: java generics extends

因此,首先,我将指出我的问题不是要对一个类应用多个泛型。我知道您可以用逗号简单地做到这一点。

我的问题是,是否有一种方法可以对泛型进行多种扩展。例如:

public class Foo<? extends String>{}
public class Bar<? extends StringBuilder>{}
//combined
public class FooBar<? extends String, StringBuilder>{}
//or perhaps
public class FooBar<? extends String || StringBuilder>{}

我知道FooBar类不会编译,但希望对解释我的问题和指定的意图有用。最后重申一下我的问题:是否可以在通用子句中扩展两个类,或者采用一种间接模拟这种行为的方式?

请注意,我不是在询问泛型的工作方式,是扩展的工作方式,也不会涉及泛型的使用方式和时间的任何内容,我已经知道了如果问题需要澄清,我将进行编辑以尽我所能提供进一步的理解。

2 个答案:

答案 0 :(得分:3)

一个类不可能同时扩展StringStringBuilder,因为类只有一个父类。但是,它们可以实现多个接口,您可以使用&指定这些接口。

class FooBar<T extends String & Runnable & Collection<Integer>> {}

(请注意,String是最终的,因此实际上不可能满足上述约束。)

答案 1 :(得分:1)

因此,约翰所说的开箱即用是不可能的,但是您仍然可以使用所谓的Either类型来实现类似的行为,该类型用于表示您可以选择2个中的1个类型。

您可以通过简单的Google搜索轻松找到完全实现的Either类,例如github上的这一类

对于下面的代码段,请考虑以下简化版本:

public class Either<L, R> {
    private final L left;
    private final R right;
    private final boolean isRight;

    private Either(L left, R right, boolean isRight) {
        this.left = left;
        this.right = right;
        this.isRight = isRight;
    }

    public static <L, R> Either<L, R> left(L left){
        return new Either<>(left, null, false);
    }

    public static <L, R> Either<L, R> right(R right){
        return new Either<>(null, right, true);
    }

    public <T>  T fold(Function<L,T> foldLeft, Function<R, T> foldRight){
        return isRight ? foldRight.apply(right) : foldLeft.apply(left);
    }
}

现在可以说您具有某种应接受StringStringBuilder的方法的接口:

public interface IFooBar <T extends Either<? extends String, ? extends StringBuilder>>{
    String  doSomething(T t);
}

实施:

class FooBar implements IFooBar<Either<String, StringBuilder>> {
    @Override
    public String doSomething(Either<String, StringBuilder> either) {
        return either.fold(s -> "String: " + s, sb -> "StringBuilder:" + sb);
    }
}

然后您可以像这样简单地使用它:

public static void main(String[] args) {
    IFooBar<Either<String, StringBuilder>> fooBar = new FooBar();
    // Since in this case it is single method interface you can even use lambda expression
    // IFooBar<Either<String, StringBuilder>> fooBar = either -> either.fold(s -> "String: " + s, sb -> "StringBuilder:" + sb);
    System.out.println(fooBar.doSomething(Either.left("Foo")));
    System.out.println(fooBar.doSomething(Either.right(new StringBuilder("Bar"))));
}

希望对您有所帮助。