2013-06-10 2 views
2

Вчера я задал знакомый вопрос, но возникла еще одна проблема.Полиморфизм - Неоднозначная ошибка

class Cat { 
    public void isClawedBy(Cat c, Kitten k){ 
     System.out.println("Clawed by a cat"); 
    } 
} 

class Kitten extends Cat{ 
    public void isClawedBy(Kitten k, Cat c){ 
     System.out.println("Clawed by a Kit"); 
    } 
} 


Cat g = new Cat(); 
Cat s = new Kitten(); 
Kitten t = new Kitten(); 

g.isClawedBy(s,t); 
s.isClawedBy(t,s); 
t.isClawedBy(t,t); 

Вопрос: Меня путают около t.isClawedBy(t,t);. Я понимаю, что s.isClawedBy(t,s); выдает ошибку, потому что s имеет статический тип cat.

Но t.isClawedBy(t,t); выбрасывает «Метод isClawedBy (Kitten, Cat) неоднозначен для ошибки типа Kitten». Если я меняю код на t.isClawedBy(s,t); или t.isClawedBy(t,s);, он работает, но не уверен, почему он не работает для (t, t).

Заранее спасибо

+0

Мне нравится, как вы хотите понять, пытаясь с множеством комбинаций :) – nachokk

+0

Другие уже объяснили. Только один совет - подумайте об использовании аннотации @Override, чтобы сообщить компилятору о ваших намерениях. Вы не будете удивлены, и компилятор скажет вам, что вы не переопределяете какой-либо метод. – wjtk

ответ

1

В вызовах метода Java решаются динамически. Когда вы вызываете метод, JVM пытается найти метод, который соответствует имени метода i.e, типам параметров и типам возвращаемых данных. Он делает это, просматривая таблицу методов используемого класса, которая также будет содержать сигнатуры методов супер типов.

При проверке, подходит ли подпись в таблице методов, она будет учитывать супертипы типов параметров (и возврата). В случае t.isClawedBy(t,t) мы имеем два метода, которые могут соответствовать методу, определенному в совпадениях Kitten, и которые определены в совпадениях Cat - обратите внимание, что это разные методы, так как они имеют разные типы параметров.

Как два разных метода соответствуют вызову метода: неоднозначный.

Для isClawed(s,t) и isClawed(t,s) нет двусмысленности, так как s является котенком и не может быть кошкой.

+0

Это не просто двойной матч - оба кандидата одинаково хорошо совпадают. Если бы один метод был «более конкретным», чем другой, он был бы выбран, даже если бы было два матча. См. JLS, [15.12.2.5 Выбор наиболее конкретного метода] (http://docs.oracle.com/javase/specs/jls/se5.0/html/expressions.html#15.12.2.5) –

0

Это потому, что вы не переопределить этот метод.

Для t.isClawedBy(t,t); существует два возможных метода выполнения. Метод Cat's isclawed и метод Kitten's isclawed.

Для переопределения метода пареметры должны быть одинаковыми.

1

Это неоднозначно, потому что Kitten s is Cat s.

Таким образом, учитывая:

Cat isClawedBy(Cat c, Kitten k) 
Kitten isClawedBy(Kitten k, Cat c) 

Для Kitten, оба метода доступны. A Kitten - Cat, поэтому запрос на Cat.isClawedBy(Cat, Kitten) с двумя аргументами Kitten подходит подписи. Аналогично, звонок в Kitten.isClawedBy(Kitten, Cat) с двумя Kitten s также соответствует подписи.

Компилятор не может сказать, какой метод был предназначен.

0

котенка расширяет кошку, так котенок получает atributs и методу кошки, так что класс котенка знает 2 метод

  1. общественного недействительный isClawedBy (Cat с, Котиком к)
  2. общественных недействительным isClawedBy (Котик к, Кошка с)

Но доцент знаю metoth общественного недействительными isClawedBy (Котик к, Котик к), так что знаю, что доцент делать, когда и называть isClawedBy (т, т);

Смежные вопросы