Как Java-компилятор без приведения типов вызывает правильную функцию equals () в подклассе? - PullRequest
0 голосов
/ 27 августа 2018

У меня есть ScheduledSessionViewModel класс, который расширяет AbstractSessionViewModel. Обе эти функции имеют реализацию функции equals () .

class AbstractSessionViewModel {
   @Override public boolean equals(Object o) {
      return /* some logic */
   }
}

class ScheduledSessionViewModel extends AbstractSessionViewModel {
   @Override public boolean equals(Object o) {
      if (!super.equals(o)) return false;

      return /* some logic */;
   }
}

Так как я использую новые Android ListAdapter, я реализую DiffUtil.ItemCallback<T>, и у меня есть следующий метод:

@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
   if (oldItem instanceof ScheduledSessionViewModel && !(newItem instanceof ScheduledSessionViewModel)){
     return false;
   } else if (!(oldItem instanceof ScheduledSessionViewModel) && newItem instanceof ScheduledSessionViewModel){
     return false;
   } else if (oldItem instanceof ScheduledSessionViewModel){
     return ((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
   } else {
     return oldItem.equals(newItem);
   }
}

Что странно, это то, что компилятор показывает мне предупреждение, что в следующем выражении

((ScheduledSessionViewModel) oldItem) .equals ((ScheduledSessionViewModel) newItem);

тип приведения не требуется .

Как это возможно? Как Java-компилятор может обнаружить, что oldItem имеет тип ScheduledSessionViewModel?

Ответы [ 2 ]

0 голосов
/ 28 августа 2018

Примечание: после разъяснения, приведенного выше, я пришел к выводу, что при правильно реализованном методе equals() метод ниже

@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
  if (oldItem instanceof ScheduledSessionViewModel && !(newItem instanceof ScheduledSessionViewModel)){
    return false;
  } else if (!(oldItem instanceof ScheduledSessionViewModel) && newItem instanceof ScheduledSessionViewModel){
    return false;
  } else if (oldItem instanceof ScheduledSessionViewModel){
    return ((ScheduledSessionViewModel)oldItem).equals((ScheduledSessionViewModel)newItem);
  } else {
    return oldItem.equals(newItem);
  }
}  

может быть реорганизован и если утверждения не нужны. Реализация метода equals() должна обо всем позаботиться.

Конечный результат:

@Override public boolean areContentsTheSame(AbstractSessionViewModel oldItem, AbstractSessionViewModel newItem) {
    return oldItem.equals(newItem);
}  
0 голосов
/ 28 августа 2018

Как Java-компилятор может обнаружить, что oldItem имеет тип ScheduledSessionViewModel?

Нет, это не так; компилятор знает только, что oldItem имеет тип AbstractSessionViewModel.

Но это не имеет значения. Компилятор знает, что у AbstractSessionViewModel есть метод equals(Object), поэтому у объекта типа фактический тоже есть. Таким образом, компилятор гарантирует, что метод equals(Object) доступен во время выполнения.

Как это реализовано , известно только во время выполнения. Среда выполнения ищет соответствующий метод на основе набора правил, определенных JLS.

...