Что не так с этим примером наследования свойств Java? - PullRequest
13 голосов
/ 07 октября 2010

Inheritance.java

public class InheritanceExample {
  static public void main(String[] args){
    Cat c = new Cat();
    System.out.println(c.speak());

    Dog d = new Dog();
    System.out.println(d.speak());
  }
}

Animal.java

public class Animal {
  protected String sound;
  public String speak(){
    return sound;
  }
}

Cat.java

public class Cat extends Animal {
  protected String sound = "meow";
}

Dog.java

public class Dog extends Animal {
  protected String sound = "woof";
}

Вывод:

null
null

Мои животные не могут говорить.Так грустно.

Ответы [ 7 ]

10 голосов
/ 07 октября 2010

Поля не являются полиморфными.Вы объявили три совершенно разных поля: поля в Cat и Dog shadow или hide в Animal.

.Простейший (но не обязательно лучший) способ получения текущего кода - удалить sound из Cat и Dog и установить значение унаследованного поля sound в конструкторе для Cat и Dog.

Лучшим подходом было бы сделать Animal абстрактным и дать ему защищенный конструктор, который принимает звук ... тогда конструкторы Cat и Dogзвоните super("meow") и super("woof") соответственно:

public abstract class Animal {
    private final String sound;

    protected Animal(String sound) {
        this.sound = sound;
    }

    public String speak(){
        return sound;
    }
}

public class Cat extends Animal {
    public Cat() {
        super("meow");
    }
}

public class Dog extends Animal {
    public Dog() {
        super("woof");
    }
}
4 голосов
/ 07 октября 2010

Вы не можете переопределить поля класса, только методы. Поле sound в ваших классах Dog и Cat фактически скрывает поле sound в суперклассе Animal.

Однако вы можете получить доступ к полям суперкласса из подклассов, чтобы вы могли сделать что-то вроде этого:

public class Dog extends Animal {
  public Dog() {
    sound = "woof";
  }
}

public class Cat extends Animal {
  public Cat() {
    sound = "meow";
  }
}

Или вы можете сделать класс Animal абстрактным, а также объявить метод speak абстрактным, а затем определить его в подклассах:

public abstract class Animal {
  public abstract String speak();
}

public class Dog extends Animal {
  public String speak {
    return "woof";
  }
}

public class Cat extends Animal {
  public String speak {
    return "meow";
  }
}
0 голосов
/ 07 октября 2010

Вы не позволяли своим животным говорить! вы должны сделать так:

Cat.java:

public class Cat extends Animal {
//  protected String sound = "meow";

    public Cat(){
        this.sound = "cat";
    }

}

Dog.java:

public class Dog extends Animal {
// protected String sound = "woof";

    public Dog(){
        this.sound = "dog";
    }
}

только потому, что в Cat или Dog есть два члена, которые "наследуют", и тот, который унаследован от Animal скрыт без значения (поэтому он печатает ноль), другой является особенным для Cat или Dog, которому присваивается значение. Таким образом, вы должны использовать указатель 'this', чтобы процитировать оригинальный элемент 'sound'.

0 голосов
/ 07 октября 2010

Способ Java (TM) - объявить защищенную строку getSound () в Animal.java и реализовать ее в подклассах.

0 голосов
/ 07 октября 2010

Ты , тень поле, унаследованное от Animal.У вас есть несколько вариантов, но самый красивый способ сделать это - передать звук в конструкторе:

public class Animal {
  private final String sound;
  protected Animal(String sound){
    if (sound == null)
      throw new NullPointerException("sound");
    this.sound = sound;
  }
  public String speak(){
    return sound;
  }
}

public class Cat extends Animal {
  public Cat(){ super("meow"); }
}

public class Dog extends Animal {
  public Dog(){ super("woof"); }
}

Таким образом, вы можете убедиться, что Animal всегда имеет правильный звукстроительство.

0 голосов
/ 07 октября 2010

Метод будет искать в пространстве имен своего класса для разрешения полей. Хотя методы, определенные в подклассах, могут искать иерархию для разрешения полей, то же самое нельзя сказать о классах, определенных выше в иерархии, то есть суперклассы не будут смотреть вниз по иерархии для разрешения полей [и их значений]

0 голосов
/ 07 октября 2010

Ты прячешь поля. sound в Animal отличается от String с sound в Cat.

Одним из возможных решений является создание конструктора и просто сказать

super.sound = "meow";

вместо того, чтобы в теле класса сказать

protected String sound = "meow";

для установки поля.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...