Итак, прежде всего, я уточню, что мой вопрос не относится к применению нескольких дженериков к классу. Я знаю, что вы можете сделать это просто с запятой.
Мой вопрос в том, есть ли способ иметь несколько возможных расширений для дженериков. Например:
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 не скомпилируется, но я надеюсь, что это поможет объяснить мой вопрос и указанное намерение. Наконец, повторю мой вопрос: возможно ли, чтобы два класса были расширены в общем предложении или способом, который косвенно имитировал бы такое действие?
Примечание. Я нет спрашиваю, как работают дженерики, ни — как работают расширения, ни — все, что связано с тем, как и когда использовать дженерики, потому что я это уже знаю. Если вопрос нуждается в разъяснении, я отредактирую, чтобы обеспечить дальнейшее понимание в меру своих возможностей.
@Emax Я не совсем уверен, что еще определить. Класс есть, дженерики есть. И намерение таково, что "?" может расширять как String, так и StringBuilder. Если бы это было так ? расширяет число, то общим может быть число, целое число, двойное число и т. д. Но цель состоит в том, чтобы иметь двух братьев и сестер, а не отношения родитель-потомок.
Итак, если я правильно понял, вы хотите иметь общий, который будет либо из иерархии String или StringBuilder?
@FilipRistic правильно
Класс не может расширять и String
, и StringBuilder
, поскольку классы имеют только один родительский класс. Однако они могут реализовывать несколько интерфейсов, которые вы можете указать с помощью &
.
class FooBar<T extends String & Runnable & Collection<Integer>> {}
(Обратите внимание, что String
является окончательным, поэтому на самом деле невозможно удовлетворить указанному выше ограничению.)
Большое спасибо. Я предполагаю, что причина в том, что по той же причине множественное наследование для классов не разрешено?
Итак, то, что вы просите, невозможно из коробки, как сказал Джон, но вы все равно можете добиться аналогичного поведения, используя так называемый тип Either
, который используется для представления ситуации, когда вы можете выбрать один из двух типов.
Вы можете легко найти полностью реализованный класс Either
с помощью простого поиска в Google, например, этот на гитхаб.
Для фрагмента кода ниже давайте рассмотрим эту упрощенную версию:
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"))));
}
Я надеюсь, что это поможет вам.
Я попробую это. Судя по беглому взгляду, это может сработать. Спасибо.
Можете ли вы привести полный пример? потому что этот вопрос не совсем ясен