2013-12-04 2 views
0

Я пытаюсь достичь следующий API:Generic регистратор Синтаксис интерфейса ошибки

Logger<Widget> logger = new SimpleLogger<Widget>(); 

// clazz == Widget.class 
Class<?> clazz = logger.getLoggerClass(); 

Logger<Fizz> fizzLogger = new SimpleLogger<Fizz>(); 

// clazz now equals Fizz.class 
clazz = fizzLogger.getLoggerClass(); 

У меня есть:

public interface Logger<T> { 
    public T getLoggerClass(); 

    public void setLoggerClass(T clazz); 

    public void logTrace(String trace); 
} 

А потом SimpleLogger:

public class SimpleLogger<T> implements Logger<T> { 
    private Class<?> loggerClass; 

    @Override 
    public T getLoggerClass() { 
     return loggerClass; 
    } 

    @Override 
    public void setLoggerClass(T clazz) { 
     this.loggerClass = clazz; 
    } 

    @Override 
    public void logTrace(String trace) { 
     System.out.println("TRACE: " + trace); 
    } 
} 

Однако в SimpleLogger, на следующей строке кода:

@Override 
public T getLoggerClass() { 
    return loggerClass;  <==== this line here 
} 

Я получаю следующую ошибку синтаксиса:

Type mismatch: cannot convert from Class to T

Почему я получаю это, и что я могу сделать, чтобы сохранить нужный мне API и исправить ошибку синтаксиса? Есть ли лучший способ написать это с использованием универсальных методов? Заранее спасибо!

ответ

2

Вы заявляете, что ваш класс параметризован каким-то типом T, который, как вы говорите, может быть любым классом, а затем вы хотите, чтобы этот класс был подтипом Class<?>. Это несовместимо.

Либо вы хотите T на самом деле бытьClass<?>:

public interface Logger<T extends Class<?>> { 
    T getLoggerClass(); 
    void setLoggerClass(T klass); 
} 

Или, наоборот, вы хотите вернуть класс T вместо самой T.

public interface Logger<T> { 
    Class<? extends T> getLoggerClass(); 
    void setLoggerClass(Class<T> klass); 
} 
+0

Благодарности @Daniel Pryden (+1) - это начинает обретать смысл. Но я думаю, я все еще не уверен, какой из этих двух вариантов я хочу. Можете ли вы посмотреть на желаемый API, который у меня есть в начале моего вопроса, и пояснить мне, какой из двух вариантов я ищу? В принципе, если я объявляю «SimpleLogger », а затем вызываю метод «getLoggerClass» этого журнала, я хочу «Widget.class». Etc для любого другого класса. Еще раз спасибо! – IAmYourFaja

+1

С первым вариантом вам нужно было бы объявить 'SimpleLogger >', но тогда тип параметра будет соответствовать типу, возвращаемому из 'getLoggerClass()' (они оба будут 'T'). Похоже, вам нужен второй вариант: вам нужен один тип в параметре ('Widget') и другой тип, возвращаемый' getLoggerClass() '(' Class ', потому что вы хотите иметь возможность назначить его переменной типа «Класс »). –

+0

Еще раз спасибо @ Daniel Pryden (снова +1) - теперь, когда вы так объясняете, звучит так, будто я хочу вариант №2. Однако как я могу объявить «SimpleLogger»? Будет ли это «открытый класс SimpleLogger », реализует Logger ', или это будет' public class SimpleLogger реализует Logger 'или что-то еще? Обещай, это последний вопрос! Еще раз спасибо всем за помощь! – IAmYourFaja

0

Вы получаете несоответствие типов здесь, потому что Class не T.

Если вам действительно нужно вернуть T в getLoggerClass() вот так:

возвещать loggerClass как:

private Class<T> loggerClass; 

Определите T:

private T t;` 

Затем написать конструктор:

public SimpleLogger(T t) 
{ 
    super() // You know the constructors of Logger... 
    this.t = t; 
} 

Итак становится легко:

@Override 
public T getLoggerClass() { 
    return t; 
} 
Смежные вопросы