2015-08-29 1 views
1

Я изучаю Java, пытаясь понять наследование. Я не мог понять, почему переопределенный метод выполняется в подклассе walk(), но не в другом методе xyz().Почему я не могу вызвать метод подкласса, используя ссылку родительского типа, которая ссылается на экземпляр подтипа?

class Person{ 
    public void walk() { System.out.println("walking like a person "); } 
    } 

    public class Soldier extends Person{ 
    @override 
    public void walk() { System.out.println("marching like a soldier "); } 
    public void xyz() { System.out.println("xyzng like a pro"); } 

    public static void main(String[] args) { 

     Person sp = new Soldier(); 
     sp.walk(); 
     sp.xyz(); 
    } 
    } 

Вот мой вопрос, если метод следующий вызов отлично работает и вызывает метод Soldier ходьбы,

sp.walk(); 

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

sp.xyz(); 
+0

Поскольку 'sp' гарантированно будет тип Person, а не солдат, поскольку это также правильный код' Человек зр = new Person(); ' –

ответ

0

Возможно, вы захотите ознакомиться с этим answer.

В основном, xyz метод определен в подклассе Person и в общем случае компилятор не может знать (и не должен знать), является ли ссылка экземпляр Soldier или какой-либо другой подкласс, который не определяет xyz метод.

0

В Java «объекты» сами не являются значениями - их всегда следует манипулировать с помощью ссылок; когда вы создаете объект, вы получаете ссылку; когда вы обращаетесь к полю или вызываете метод, вы делаете это через ссылку. Когда вы назначаете одну ссылку на другую, она копирует ссылку, поэтому у вас есть несколько указателей на один и тот же объект.

Ваш вопрос спрашивает, почему Soldier.xyz() не доступен, когда Soldier объект хранится в Person ссылки. Ответ: пересечение «полиморфизма» и «статической типизации». Поскольку Java - это , статически введенный во время компиляции, вы получаете определенные гарантии от компилятора , но вы вынуждены следовать правилам в обмен или код не будет компилироваться. Здесь соответствующая гарантия заключается в том, что каждый экземпляр подкласс (например, Soldier) может использоваться как экземпляр его класса супер (например, Person).

Пожалуйста, обратите внимание на это поясняется более подробно thread Как экскурсовода учебник по-настоящему понять наследование, пожалуйста, посмотрите на это article

+0

Спасибо, что объясняет многое. Затем, когда был вызван именно Soldier.walk()? потому что его, кажется, во время компиляции вызывается Person.walk(). –

+0

Экземпляр Солдата приводится к экземпляру Person, и именно поэтому был вызван метод 'walk()' s солдата. Так что это все еще экземпляр Солдата, но доступны только методы Лица –

2

В момент компиляции родительского класса эталонным «зр 'может видеть только метод внутри него. если вы хотите получить доступ как ((Солдат) sp) .xyz()

0

Это понятно. , потому что ваша ссылка на объект (sp) имеет тип Person, это означает, что sp содержит все свойство и методы только Person. Даже вы получаете экземпляр Солдата, но ваша ссылка еще от типа Person.

0
  • Person - класс.
  • sp является объектом, он является экземпляром Person
  • класса Person не метод с именем xyz(), thereforce sp.xyz() не работает.

enter image description here

(У вас есть опечатка, мы используем @Override, не @override)

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