这个Java属性继承的例子有什么问题?

时间:2010-10-07 06:55:44

标签: java inheritance

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 个答案:

答案 0 :(得分:10)

字段不是多态的。您已声明了三个完全不同的字段... CatDog 阴影隐藏 Animal中的字段

获取当前代码的最简单(但不一定是最佳)方法是从soundCat中删除Dog,并设置继承的值sound和Cat的构造函数中的em> Dog字段。

更好的方法是使Animal抽象,并给它一个受保护的构造函数来获取声音......然后CatDog的构造函数会调用{{1}分别和super("meow")

super("woof")

答案 1 :(得分:4)

您不能覆盖类字段,只能覆盖方法。 soundDog类中的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";
  }
}

答案 2 :(得分:0)

你隐藏着田野。 sound中的AnimalString中的sound不同Cat

一种可能的解决方案是创建一个构造函数,只需说

super.sound = "meow";

而不是在课堂上说

protected String sound = "meow";

设置字段。

答案 3 :(得分:0)

方法将在其自己的类'命名空间中查找以解析字段。虽然子类中定义的方法可以查找层次结构来解析字段,但对于在层次结构中更高层定义的类,情况也是如此,即,超类不会向下查看层次结构以解析字段[及其值]

答案 4 :(得分:0)

shadowing继承自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始终具有有效的声音,直接来自构造。

答案 5 :(得分:0)

Java(TM)方法是在Animal.java中声明受保护的String getSound()并在子类中实现它。

答案 6 :(得分:0)

你不允许你的动物说话! 你应该这样做:

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的成员 隐藏没有值(因此它打印为null);另一个对Cat或Dog来说是特殊的,它被赋值。 所以你应该使用指针'this'来引用原始成员'sound'。