2016-01-23 1 views
1
public class HelloWorld{ 

    public static void main(String []args){ 
     Ball b=new Ball(); 
     System.out.println(b.getName()); 
    } 
} 

class Shape{ 
    private String name; 
    Shape(){ 
     name="Shape"; 
    } 
    public String getName(){ 
     return name; 
    } 
} 

class Ball extends Shape{ 
    private String name; 
    public Ball(){ 
     name="Ball"; 
    } 
} 

Почему я получаю вывод как «Форма» вместо «Бал»?Какие элементы данных используют класс child в Java?

Я получаю тот же результат, даже если я изменю

private String name; 

в

public String name; 

в обоих Shape и Ball классов.

+1

'имя' является' частным'. Он существует независимо, каждый «класс». –

+0

@BoristheSpider Даже если 'name' был общедоступным, у вас все равно будет два отдельных поля. Это всего лишь два поля, которые имеют одно и то же имя в двух разных классах. – dhke

ответ

0

В Java все наследование переходит от суперкласса к подклассу, включая переменные экземпляра и методы.

Значение, если вы хотите «вызвать метод суперкласса» с «параметрами подкласса», вы просто создаете объект в подклассе и вызываете ваш метод.

Потому что уникальный метод с именем getName() находится в вашем суперклассе, когда invok метод getName(), во-первых, поиск в подклассе, когда его нет, он ищет в суперклассе.
Для этого у вас есть: Shape вместо Ball:

3

Есть два name поля объекта Ball - один, определенные в Ball классе и один в Shape классе.

Когда вы создаете поле с таким же именем в дочернем классе, вы должны указать поле родительского класса hide. Попытайтесь избежать этого в своем коде. Обычно вы можете получить доступ к родительскому полю с супер ключевым словом, например super.name, но поскольку ваши поля являются частными, вы не можете этого сделать.

Метод Shape#getName возвращает поле name со своего класса. Поля в Java не переопределяют родительские поля, такие как методы, поэтому Shape.name в любом случае не заменяется Ball.name.

Обзор этот код, чтобы увидеть, как ссылочный тип определяет поле использовать

Ball ball = new Ball(); 
println ball.name; // prints Ball, because reference type if Ball 

Shape shape = ball; // this is same ball object 
println shape.name; // prints Shape, because reference type is Shape 

println ball.getName(); // prints Shape - getter in Shape class can only see Shape fields 

Если добавить геттер в Ball классе, то вызовы метода всегда будет возвращать «Бал»

println ball.getName(); // will print Ball 
println shape.getName(); // will print Ball 
+0

Я получаю «Shape» как вывод, даже если «имя» изменено с «private» на «public» – TryinHard

+0

@TryinHard. Но 'Shape' знает только о' name', объявленном в 'Shape'. Он всегда обращается к этому полю. Поля не являются виртуальными, т. Е. 'Shape.name' и' Ball.name' являются двумя отдельными полями. Если вы сделаете 'имя' защищенным в' Shape' и полностью отбрасываете 'name' из' Ball', вы получите результат, который вы намеревались (но это не очень хорошо для OO). – dhke

+0

@TryinHard Я попытался объяснить, как переопределение метода отличается от скрытия поля – AdamSkywalker

0

при создании новый шар. В шаровом конструкторе первое, что выполняется неявно, - это супер-конструктор без аргументов. Это означает, что конструктор формы выполняется с настройкой name = "shape". Тогда из-за того, что метод getName не перегружен, вы получаете значение «shape».

1

Нет волшебства переопределение по названию для полей. Если у вас есть поле в классе и поле с тем же именем в подклассе, у вас есть два разных поля.

Shape.name и Ball.name - полностью отдельные объекты.Если установить оба поля public, вы получите:

Shape s = new Ball(); 
s.getName(); // => returns "shape" 
s.name   // yields "shape", because you are accessing a class of type `Shape`. 
((Ball)s).name // yields "ball", because you are accessing a class of type `Ball` 

На данный момент Ball на самом деле имеет два различных name поля: один наследуемые от Shape и заявленных в самом Ball классе.

Если у вас есть name внутри Ball, вы получите первый, определяемый правилами поиска символов, который равен Ball.name. Если Shape.name - protected или public, он будет доступен super.name. Примечание еще раз: есть два отдельных поля имени, по одному для каждого класса. Они просто имеют одно и то же имя поля, но в остальном полностью разделены.

Те же правила подстановки применяются также для Shape: Когда Shape.getName() собран, он пытается найти поле с именем nameво время компиляции и использует это находит, который является единственным доступным в данный момент: один в Shape. Поиск является статическим.

Однако, если Shape.name является закрытым, вы не можете получить к нему доступ из класса Ball.

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