Подтвердить что ты не робот

Аргумент метода расширяет интерфейс классов

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

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

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

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

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

myMethod(Class<? extends BasicObject implements CodeObject> clazz){...}
4b9b3361

Ответ 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)
    }
    ...
}