зачем переопределять вызов метода из подкласса, если я выполнил преобразование?

я только начал изучать java::Inheritance и запутался, смешивая Up-Casting.

class Example{
     public void methodOne(){
        System.out.println("Example::Method_1");
     }

     public void methodTwo(){
        System.out.println("Example::Method_2");
     }
}

public class Test extends Example{

     public void methodTwo(){                  //Method overriding
        System.out.println("Test::Method_2");
     }

     public void methodThree(){
        System.out.println("Test::Method_3");
     }

    public static void main(String[] args){

        Example exa = new Test();             // UpCasting

        exa.methodOne();                      // Printing Example::Method_1
        exa.methodTwo();                      // Printing Test::Method_2
        // exa.methodThree();                 // Error : can not find symbol
 }
}

может кто-нибудь объяснить, что здесь происходит??


person Avinash Kumar    schedule 13.08.2017    source источник
comment
Вы можете использовать аннотацию @Override, чтобы отметить, что метод переопределяет   -  person baao    schedule 13.08.2017
comment
Я новичок, извините за любую ошибку, здесь я хочу знать, почему вызывается метод подкласса, если метод переопределен?   -  person Avinash Kumar    schedule 13.08.2017


Ответы (3)


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

Но во время вызова не имеет значения, какой это тип времени компиляции. Что действительно важно в этом случае, так это тип объекта во время выполнения. Это Test, поэтому метод сначала ищется на Test.

Для methodOne() все немного иначе: Test не переопределяет его, поэтому вызывается версия из его суперкласса (Example).

person Roman Puchkovskiy    schedule 13.08.2017

Класс Test расширяет Example и переопределяет реализацию methodTwo при добавлении нового метода methodThree. Теперь в тебе главное

public static void main(String[] args){

        Example exa = new Test();             // UpCasting

        exa.methodOne();                      // Printing Example::Method_1
        exa.methodTwo();                      // Printing Test::Method_2
        // exa.methodThree();                 // Error : can not find symbol
 }

Статический тип переменной exa равен Example, следовательно, использование API ограничено общедоступными методами, определенными в классе Example, поэтому вызов exa.methodThree() (не определенный Example) является незаконным.

В то время как для методов, которые определены в классе Example, существует динамическая привязка во время выполнения, что приводит к конкретной реализации на основе ссылки, на которую указывает переменная exa. Поэтому вызов exa.methodTwo() приводит к выполнению переопределенной функции, так как динамический тип Test. И поскольку Test не переопределяет methodOne, вызов exa.methodOne() приведет к реализации, определенной Example.

person Artem Barger    schedule 13.08.2017

если мы создаем объект подкласса и используем ссылку на класс ужина, тогда происходит динамическая привязка во время выполнения, что означает, что во время выполнения java решает, какую вещь следует вызывать. в вашем случае: 1. exa.methodOne(); methodOne принадлежит суперклассу и не переопределяется в дочернем классе, поэтому будет выполняться метод родительского класса. здесь, если вы создадите объект типа Test test = new Test();, то и test.methodOne() даст вам тот же результат.

  1. exa.methodTwo(); здесь methodTwo переопределяется в дочернем классе, поэтому во время выполнения переопределенный метод будет связан, и он будет выполнен.

  2. в третьем случае это дает ошибку, потому что вы используете ссылку на родительский класс, но methodThree() не является частью родителя, поэтому возникает ошибка компиляции. если вы хотите вызвать третий метод, вы можете позвонить так: Test test = new Test(); test.methodThree()

К вашему сведению,

в целях безопасности мы всегда должны использовать аннотацию @Override в дочерних методах вызова, если мы хотим переопределить любой метод родительского класса. это поможет избежать каких-либо сбоев переопределения метода.

person user2862544    schedule 13.08.2017