О переопределении метода - PullRequest
0 голосов
/ 17 июня 2011

Для следующего сегмента кода Java метод «run» встречается четыре раза.Я довольно смущен отношениями этих четырех случаев «бега».Оригинальный код довольно длинный, я просто оставляю часть, связанную с моим вопросом.

   1. public final class Job extends AbstractJob {  
   2.   private Job( ) {  
   3.   }  
   4.   public static void main(String[] args) throws Exception {    
   5.            new Job( ).run(new Path("testdata"), output, 10 );  
   6.   }  
   7.   
   8.   @Override  
   9.   public int run(String[] args) throws IOException, ClassNotFoundException,      InterruptedException {  
  10.         run(input, output, alpha0);  
  11.         return 0;  
  12.   }    
  13.   public void run(Path input,  Path output,  double alpha0)  
  14.     throws IOException, ClassNotFoundException, InterruptedException {      
  15.     ClusterDriver.run(directoryInput, output, alpha0);      
  16.   }  
  17. }  

Можно ли понять последовательность вызова этого сегмента кода следующим образом:

Сначала вызывается метод run в строке 5.Из-за его особой установки параметров, 3 параметров, компилятор автоматически использует метод запуска, определенный в строке 13 (если у нас есть только один параметр в строке 5, то компилятор будет использовать метод запуска, определенный в строке 9.

Для метода run, определенного в строке 9, он вызовет метод run в строке 10, что по сути является методом run, определенным в строке 13.

Правильно ли мое понимание?

Ответы [ 4 ]

2 голосов
/ 17 июня 2011

Да, это правильно, за исключением того, что это метод с перегрузкой , не переопределяющий.

В этом классе определены два метода run, в строках 9 и 13, сразное количество параметров.Следовательно, метод run является перегруженным .( Переопределение происходит, если метод виртуального базового класса переопределен в подклассе - это, очевидно, происходит с методом, определенным в строке 9, что подтверждается его аннотацией, но это не играет никакой роли в этом конкретном вопросе.)

И есть два вызова run (в строках 5 и 10), которые оба разрешают вызов метода с 3 параметрами (определенными в строке 13).

0 голосов
/ 17 июня 2011

Ваш базовый анализ верен.

(просто для пояснения того, что сделали другие: перегрузка - это когда методы имеют одинаковое имя, но разные сигнатуры, тогда как переопределение - это когда метод имеет одинаковое имя и аргумент типы как метод в суперклассе)

Для дальнейшего использования, вы должны знать, что разрешение метода (имя + аргументы -> выбор метода) в Java, в случае перегруженных методов, на самом деле может быть довольно трудным для понимания. Точное используемое поведение описано в Спецификации языка Java (JLS), раздел 15.12 , и включает в себя несколько общих тонкостей:

  • Разрешение перегруженного метода выполняется в во время компиляции , а не во время выполнения. (выбор из метода переопределяет с такой же сигнатурой выполняется во время выполнения на основе метода наиболее определенного подкласса.) Если компилятор знает, что аргумент является экземпляром Foo (например, его класс - Foo или подкласс Foo), тогда он будет использовать Foo в качестве класса аргумента, а не его "реальный" класс.

  • Проблемы, определяющие, какой метод используется:

    • независимо от того, является ли метод varargs или нет (имеет ... в качестве последнего аргумента, например, foo(Object a, String... b))
    • являются ли объявленные аргументы метода примитивами или примитивами с оболочкой, например float против Float
    • является ли объявленные аргументы одного метода "более конкретными", чем другие (подклассы более специфичны, чем их суперклассы)

Это сложно, но у вас есть базовое понимание.

0 голосов
/ 17 июня 2011

Вы правильно поняли большинство вещей, но я хочу исправить несколько утверждений:

if we only have one parameter in line 5, then compiler will use the run method defined in line 9 instead.

Это не совсем правильно, метод в строке 9 принимает аргументы типа String[], и вам понадобитсяпередать массив для вызова этого метода.

For the run method defined in line 9, it will call run method at line 10, which essentially is the run method defined at line 13.

В строке 10 вы получите синтаксическую ошибку, поскольку input, output, alpha0 не определены в этом методе.Вам нужно взять переданный String[] args аргумент и преобразовать его в input, output, alpha0 аргументы, чтобы он вызывал другую реализацию run.

0 голосов
/ 17 июня 2011

Значение имеет только последний запуск определения метода.

Другой метод run (который принимает String[]) вызывает этот метод, поэтому он действует как своего рода "прокси", в то время как другой вызов run в методе main может выбирать чтобы вызвать любой из двух - либо метод 'proxy' run (который принимает String[] args), либо последний метод run , который фактически выполняет "running".

...