2012-05-17 5 views
45

У меня есть следующий класс и интерфейс:Метод аргумент расширяет класс реализует интерфейс

public class BasicObject{...} 
public interface CodeObject{...} 

Я хочу, чтобы создать метод, в котором аргумент должен быть типом BasicObject и реализует CodeObject. Я пробовал этот код, но это не гарантирует, что clazz будет классом, который реализует CodeObject.

myMethod(Class<? extends BasicObject> clazz){...} 

Я хочу сделать somethign как это, но этот код не компилируется:

myMethod(Class<? extends BasicObject implements CodeObject> clazz){...} 
+0

Это похоже на тот же вопрос: http://stackoverflow.com/questions/745756/java-generics-wildcarding-with-multiple-classes – yiannis

ответ

61

Ваш шаблон класса должен расширить 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.

+3

о части с "," , какова цель «CodeObject»? класс распространяется от «BasicObject», но как насчет «CodeObject»? –

+3

Для меня это работает, только если я использую только Т как тип параметра (без класса). Полная строка: 'public void myMethod (T clazz)' –

+0

, а затем в методе, как я могу назвать геттер, принадлежащий 'BasicObject', на объект clazz? – OrangePot

0

Если не все BasicObjects реализовать CodeObject, то вы можете использовать InstanceOf/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) 
    } 
    ... 
} 
+4

Да, но я не хочу этого делать. Конечно, любой метод может использовать myMethod (Object obj), а затем использовать «obj.isInstance (...)», но это то, чего я пытаюсь избежать. Я действительно хочу, чтобы пользователи моего метода были вынуждены передать хороший параметр. – Gab

+0

Ну, если вы хотите -force- это вы можете сбой вашей программы каждый раз, когда они это делают (или просто бросают исключение IllegalArgumentException, я уверен, что они это быстрее выяснят) – Riking

7

Это подход, который немного подробен, но позволяет избежать головных болей дженериков. Создайте еще один класс, который делает простирающийся/реализацию:

public abstract class BasicCodeObject 
    extends BasicObject 
    implements CodeObject {...} 

Тогда ваш метод может быть:

public <T extends BasicCodeObject> void myMethod(Class<T> clazz) {...} 
4

Есть два подхода к вашей проблеме в зависимости от того, хотите ли вы пройти тип класса в аргумент метода, который расширяет 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 { 

} 

теперь, если вы хотите пройти сам класс, сделать

public void myMethod(Class<TargetClassType> clazz) 

или если вы хотите, чтобы передать класс объекта, напишите

public void myMethod(TargetClassType clazz) 

Любое из вышеперечисленных решений соответствует вашему вопросу, но второе проще.

Смежные вопросы