Можно ли иметь метод интерфейса, определенный с типом возвращаемого значения, а конкретная реализация определяет тип возвращаемого значения? - PullRequest
12 голосов
/ 15 сентября 2011

Я хотел бы создать интерфейс:

public interface OperandValue
{
    <T> T getValue();
}

Затем я хотел бы иметь конкретную реализацию, подобную этой:

public class NumberOperandValue implements OperandValue
{
    @Override
    public <Integer> Integer getValue()
    {
        // some integer value that is set elsewhere
        return 1;
    }
}

Eclipse подчеркивает <Integer> предоставлениемне предупреждение, которое говорит:

Параметр типа Integer скрывает тип Integer

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

1 Ответ

23 голосов
/ 15 сентября 2011

Вы, вероятно, хотите изменить интерфейс на:

public interface OperandValue<T>
{
    T getValue();
}

И реализацию на:

public class NumberOperandValue implements OperandValue<Integer>
{
    @Override
    public Integer getValue()
    {
        // some integer value that is set elsewhere
        return 1;
    }
}

Теперь вы говорите интерфейсу, какой тип вы хотите, чтобы этот метод возвращал,Другими словами, вы делаете интерфейсный тип универсальным, а не объявление метода.Но, похоже, это то, что вы хотите.

В качестве примечания:

public <Integer> Integer getValue()

На самом деле означает «определить параметр общего типа с именем« Integer »», где getValue возвращаеттип "Integer", который вы только что определили.

Ответ на комментарии Стива ниже :

, когда я удаляю <Integer> из моей реализации метода, после чего я получаю предупреждение: Type safety: The return type Integer for getValue() from the type NumberOperandValue needs unchecked conversion to conform to T from the type OperandValue

Это предупреждающее сообщение указывает на то, что вы нарушаете правила при использовании шаблонов Java.Чтобы понять почему, давайте рассмотрим, что означает сигнатура метода, прежде чем удалять параметр типа <Integer>.

public <Integer> Integer getValue()

Эта подпись означает, что метод getValue возвращает значение типа Integer, где Integer определяется как параметр общего типа, определенный вами в угловых скобках.Значение строки Integer совершенно произвольно и будет иметь точно такое же значение, как:

public <T> T getValue()

Для ясности давайте придерживаться этой версии сигнатуры вашего метода для целей вашего вопроса.Что происходит, когда мы удаляем параметр типа?

public T getValue()

Теперь, если вы попытаетесь скомпилировать, вы получите сообщение об ошибке, что T не определено.Однако, поскольку ваша оригинальная сигнатура типа объявила параметр типа с именем Integer, когда вы его удалили, у вас осталось:

public Integer getValue()

Поскольку Integer - это уже aпредопределенный тип, метод подписи все еще технически допустим.Однако случайно, что имя вашего параметра типа совпадает с уже существующим типом.

Кроме того, поскольку ваш интерфейс уже объявил сигнатуру метода с обобщениями, компилятор Java выдает предупреждение при удалении его из реализации.В частности, компилятор обеспокоен тем, что в базовом классе возвращаемый тип метода - это (тип-стирается до Object) универсальный параметр с именем Integer, который не является тем же типом (и не известен как типсовместим с) системным классом с именем Integer (или java.lang.Integer, если быть точным).

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...