因此,首先,我将指出我的问题不是要对一个类应用多个泛型。我知道您可以用逗号简单地做到这一点。
我的问题是,是否有一种方法可以对泛型进行多种扩展。例如:
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类不会编译,但希望对解释我的问题和指定的意图有用。最后重申一下我的问题:是否可以在通用子句中扩展两个类,或者采用一种间接模拟这种行为的方式?
请注意,我不是在不询问泛型的工作方式,也是扩展的工作方式,也不会涉及泛型的使用方式和时间的任何内容,我已经知道了如果问题需要澄清,我将进行编辑以尽我所能提供进一步的理解。
答案 0 :(得分:3)
一个类不可能同时扩展String
和StringBuilder
,因为类只有一个父类。但是,它们可以实现多个接口,您可以使用&
指定这些接口。
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);
}
}
现在可以说您具有某种应接受String
或StringBuilder
的方法的接口:
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"))));
}
希望对您有所帮助。