Аргумент метода расширяет интерфейс классов
У меня есть следующий класс и интерфейс:
public class BasicObject{...}
public interface CodeObject{...}
Я хочу создать метод, в котором аргумент должен быть типа BasicObject и реализует CodeObject. Я пробовал этот код, но это не гарантирует, что clazz является классом, реализующим CodeObject.
myMethod(Class<? extends BasicObject> clazz){...}
Я хочу сделать что-то вроде этого, но этот код не компилируется:
myMethod(Class<? extends BasicObject implements CodeObject> clazz){...}
Ответы
Ответ 1
Ваш класс шаблонов должен расширять BasicObject
и расширять/реализовывать CodeObject
(который фактически является интерфейсом). Вы можете сделать это с помощью нескольких классов, объявленных в подстановочном определении подписи метода, например:
public <T extends BasicObject & CodeObject> void myMethod(Class<T> clazz)
Обратите внимание, что это не сработает, если вы сделаете это любым из следующих способов:
-
public <T extends BasicObject, CodeObject> void myMethod(Class<T> clazz)
Это технически допустимый синтаксис, но CodeObject
не используется; метод будет принимать любые классы, которые расширяют BasicObject
, независимо от того, расширяют ли они/реализуют CodeObject
.
-
public void myMethod(Class<? extends BasicObject & CodeObject> clazz)
public void myMethod(Class<? extends BasicObject, CodeObject> clazz)
Это просто неправильный синтаксис в соответствии с Java.
Ответ 2
Вот подход, который немного подробен, но избегает головных болей дженериков. Создайте еще один класс, который расширяет/реализует:
public abstract class BasicCodeObject
extends BasicObject
implements CodeObject {...}
Тогда ваш метод может быть:
public <T extends BasicCodeObject> void myMethod(Class<T> clazz) {...}
Ответ 3
Существует два подхода к вашей проблеме в зависимости от того, хотите ли вы передать тип класса в аргументе метода, который расширяет BasicObject
и реализует CodeObject
или объект класса, который делает это. Существуют решения для обоих.
Решение 1:
Если вы хотите передать сам Class
, вы можете сделать это, как объясняется @bontade,
public <R extends BasicObject & CodeObject> void myMethod(Class<R> clazz)
и если вы хотите передать объект Class
, вы можете написать
public <R extends BasicObject & CodeObject> void myMethod(R clazz)
Вышеприведенное является более сложным способом, связанным с дженериками.
Решение 2:
Ниже приводится более простая. Вы можете определить абстрактный класс, который расширяет класс, который вы хотите расширить и реализовать:
public abstract class TargetClassType extends BasicObject implements CodeObject {
}
теперь, если вы хотите передать сам класс, do
public void myMethod(Class<TargetClassType> clazz)
или если вы хотите передать объект класса, напишите
public void myMethod(TargetClassType clazz)
Любое из вышеперечисленных решений соответствует вашему вопросу, но второе проще.
Ответ 4
Если не все объекты BasicObjects реализуют CodeObject, вы можете использовать проверку экземпляра /class.isInstance() в вашем методе (см. http://docs.oracle.com/javase/1.5.0/docs/api/java/lang/Class.html):
myMethod(Class<? extends BasicObject> clazz)
{
if (!clazz.isInstance(CodeObject))
{
(indicate that the call was incorrect)
}
...
}