Общее наследование интерфейса в Java - PullRequest
0 голосов
/ 19 апреля 2019

Я создал интерфейс в Java следующим методом:

interface ReaderInterface{
      public <k,v> Map<k,v> fetch(k id);
      public <k,v> Map<k,v> fetchAll(); 
}

Затем я создал класс, который реализует этот интерфейс:

class JSONreaderImpl implements ReaderInterface{
    public Map<String, String> fetchAll(){ 
        // This compiler is allowing to be override from interface \
    }

    public Map<String, String> fetch(String id){ 
        // This is not being considered as an override method, compiler throwing an error to implement the fetch method 
    }

}

Мой вопрос здесь заключается в том, почему метод fetchAll рассматривается как метод переопределения при его создании в определенном классе, и почему нет метода выборки.

Не могли бы вы помочь мне понять это?

Ответы [ 4 ]

4 голосов
/ 19 апреля 2019

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

interface ReaderInterface<k, v> {
    public Map<k, v> fetch(k id);
    public Map<k, v> fetchAll();
}

class JSONreaderImpl implements ReaderInterface<String, String> {
    public Map<String, String> fetchAll() {  return null; }

    public Map<String, String> fetch(String id) {  return null;  }
}

В противном случае (параметризация каждого метода в отдельности предполагает создание реализаций, подобных

    public Map<String, Boolean> fetchAll() {  return null; }
    public Map<Integer, List<Double>> fetch(Integer id) {  return null;  }
1 голос
/ 19 апреля 2019

@ talex прав, и оригинальный вопрос определенно стоит ответить, несмотря на провокационный замысел.

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

interface Q {
  public <K, V> Map<K, V> fetch(K id);
}

у вас есть следующий интерфейс для расширения во время выполнения

interface Q {
  public Map<Object, Object> fetch(Object id);
}

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

Таким образом, следующая реализация может быть обнаружена как та же сигнатура

abstract class QA implements Q {
  public abstract Map<Integer, String> fetch(Object id);
}

но не может иметь этого в этой роли:

abstract class QA implements Q {
  public abstract Map<Integer, String> fetch(Integer id);
}

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

interface O {
    <K extends List, V> V process(K id);
}

abstract  class OA implements O {
    public abstract String process(List id);
}
1 голос
/ 19 апреля 2019

Чтобы понять, почему fetch не работает, посмотрите на следующий пример.

ReaderInterface foo = new JSONreaderImpl();
foo.<Integer, Integer>fetch(Integer.valueOf(1));

Это вызов fetch с <Integer, Integer> универсальными параметрами, но реализация ожидает, что они будут <String, String>. Чтобы этот компилятор не выдавал ошибку.

Я не понимаю, почему fetchAll работает. Вероятно, какая-то магия стирания, и на самом деле это предупреждение о «непроверенном переопределении».

0 голосов
/ 19 апреля 2019

вопросы не совсем понятны, но если это то, чего вы пытаетесь достичь

interface Reader<T>.
{ 
  Map fetchAll(); 
  Map fetch(T id); 
}

Impl

public class JSONReader implements Reader<String> 
{ 
  @Override
  Map<String, String> fetch(String id)
  { 
   // code
  }
  @Override 
  Map<String, String> fetchAll()
  { 
    //code
  }  
} 
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...