2013-05-15 3 views
3

Кроме того, наследование Java является фундаментальной особенностью языка, у меня есть некоторые вопросы.
Вот источник для моего тестирования, например:Наследование Java (переопределение и перегрузка метода)

class MyClass{ 

    public void say(String t){ 
     System.out.println("Hello MyClass "+t); 
    } 

    public void print(MyClass t){ 
     System.out.println("MyClass is printed"); 
    } 

    public void anotherPrint(int i){ 
     System.out.println("MyClass is printed again"); 
    } 
} 

class MyClass2 extends MyClass{ 

    public void say(String t){ 
     System.out.println("Hello MyClass2 "+t); 
    } 

    public void print(MyClass2 t){ 
     System.out.println("MyClass2 is printed"); 
    } 

    public void anotherPrint(double i){ 
     System.out.println("MyClass2 is printed again"); 
    } 
} 

public class HelloWorld{ 

    public static void main(String []args){ 
     MyClass klass = new MyClass2(); 

     klass.say("h"); //Question 1 (Prints: "Hello MyClass2 h") 

     klass.print(new MyClass2()); //Question 2 (Prints: "MyClass is printed") 
     klass.print(new MyClass()); //Question 3 (Prints: "MyClass is printed") 

     klass.anotherPrint(1); //Question 4 (Prints: "MyClass is printed again") 
     klass.anotherPrint(1.0); //Question 5 (Throws Exception!) 
    } 
} 

У меня есть следующие вопросы:

1. Объект по Klass является экземпляр MyClass. Почему он выполняет метод из класса MyClass2?

2,3. В вопросе 1 класс класс вызывает метод класса Class2. Здесь я использовал параметр, который подходит для каждого из переопределенных и перегруженных (одновременно) методов. Почему объект klass всегда вызывает метод из класса MyClass?

4. Это нормально. Никакого вопроса.

5. Право выбросить исключение. Объект klass не имеет этого метода с двойным параметром. Но почему он не называется методом класса MyClass2, как это случилось в вопросе 1?

ответ

8

1. Объект klass является экземпляром MyClass.

Нет это ссылочная переменная типа MyClass, но со ссылкой на объект MyClass2.

2. Почему выполнить метод из класса MyClass2?

Поскольку вы призываете say() на объект MyClass2, он выполняет say() из MyClass2. Ожидаемое поведение.

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

3. На вопросе 1 класс класс вызывает метод класса Class2. Здесь я использовал параметр, который подходит для каждого из переопределенных и перегруженных (одновременно) методов. Почему объект klass всегда вызывает метод из класса MyClass?

Это не переопределенный метод. Метод экземпляра в подклассе с та же подпись (имя, плюс номер и тип ее параметров) и тип возврата в качестве метода экземпляра в суперклассе переопределяет метод суперкласса. В методе переопределения также может быть возвращен подтип тип, возвращаемый переопределенным методом. Это называется ковариантным типом возврата. Ваши сигнатуры метода различны. Следовательно, ссылаясь на klass.print(), где klass является ссылкой MyClass, всегда будет ссылаться на print() из MyClass.

4. Право выбросить исключение. Объект klass не имеет этого метода с двойным параметром. Но почему он не называется методом класса MyClass2, как это случилось в вопросе 1?

Поскольку во время компиляции компилятор проверяет, можно ли вызвать метод на основе ссылочного типа.Здесь ссылочный тип - MyClass, а так как MyClass не определяет anotherPrint(double), компилятор жалуется. Это проверка времени компиляции. В вопросе 1 компилятор подтвердил klass.say("hi") и увидел, что существует способ в MyClass, который может быть вызван таким образом. В то время он не волновался, будет ли ссылочная переменная klass ссылаться на объект MyClass или объект MyClass2 во время выполнения. Следовательно, это сработало.

Вы можете обратиться к этим учебным пособиям Oracle here.

0

Вопрос 1: - с линией MyClass klass = new MyClass2(); вы сделали upcasting, поймав ссылочный id (объект) дочернего класса. В случае восходящего вызова вызываются методы дочернего класса. Хотя компилятор проверяет функцию say() в родительском блоке в одночасовое время, но во время выполнения компилятор видит, что мы также имеем функцию say() в дочернем элементе, поэтому он связывает его с методом дочернего класса и вызывает его. Именно по этой причине вы получаете выход для Вопроса 1 как Hello MyClass2 h

2

Экземпляр класса будет иметь методы отцов (ов) плюс его собственные методы. Если подпись одного из дочернего класса совпадает с сигнатурой метода у отца, он переопределит его.

В этом примере экземпляр MyClass2 будет иметь эти методы:

public void say(String t) //From MyClass2 (override) 
public void print(MyClass2 t) 
public void anotherPrint(double i) 
public void print(MyClass t) //Inherited from MyClass 
public void anotherPrint(int i) //Inherited from MyClass 

Но вы объявляете Klass как MyClass, поэтому он будет иметь в своем распоряжении эти методы

public void say(String t) //From MyClass 
public void print(MyClass t) 
public void anotherPrint(int i) 

Теперь, отвечая на ваши вопросы

1 - Вы вызываете метод say MyClass. Но во время выполнения на самом деле класс является объектом MyClass2, а MyClass2 переопределяет этот метод, поэтому он будет ссылаться на один из MyClass2

2,3 - Вы вызываете метод печати MyClass. Во время выполнения класс относится к MyClass2, но MyClass2 НЕ ПРЕВЫШАЕТ ЭТОТ МЕТОД. Подпись отличается. Таким образом, тот, который будет называться, - MyClass. Прекрасно работает с объектом MyClass2 в качестве параметра, поскольку MyClass2 является МойКласс

5 - МойКласс не имеет какой-либо метод, называемый anotherPrint приема двойной

+0

Наконец, я считаю, что я понял, когда переопределяется метод вызывался или нет. Но я считаю, что метод с параметром «MyClass2» полностью заполняет требования, и этот метод следует вызывать вместо другого. Не могли бы вы уточнить это объяснение? – LiTTle

+0

@LiTTle Это потому, что переменная klass объявлена ​​как MyClass, поэтому доступны только доступные методы, которые я разместил во втором блоке кода. Нет способа получения экземпляра MyClass2. Поскольку MyClass2 является классом, который расширяет MyClass, печать (MyClass t) может быть вызвана любым экземпляром MyClass или их подклассов, но вызовет print (MyClass t). Посмотрите, что Myclass2 имеет два метода печати (один берет MyClass, другой принимает MyClass2). Проверьте вопрос, заданный в вопросе 5. Пытаться вызвать anotherPrint с двойным не работает, другая команда MyClass принимает int, а не double. – Evans

0

Метод перегрузки и метод переопределение в Java является два важным понятием в Java, которая позволяет Java программист объявить метод с тем же именем, но с другим поведением. Перегрузка метода и переопределение метода основаны на полиморфизме в Java. В случае перегрузки метода метод с одним и тем же именем сосуществует в одном классе, но должен иметь другую сигнатуру метода, тогда как в случае переопределения метода метод с таким же именем объявляется в производном классе или подклассе. Перегрузка метода разрешается с использованием статического привязка в Java во время компиляции, в то время как переопределение метода разрешается с использованием динамической привязки в Java во время выполнения. Короче. Когда вы перегружаете метод в Java, его сигнатура метода была изменена, а в случае переопределения подпись метода остается такой же, но метод может быть переопределен только в подклассе. Поскольку Java поддерживает полиморфизм и разрешения объекта во время выполнения он способен вызвать перекрытый метод в Java

Подробнее: http://javarevisited.blogspot.com/2011/12/method-overloading-vs-method-overriding.html#ixzz34EEhLp2u

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