什么';这个Java属性继承的例子有什么问题? 继承.java Animal.java Cat.java Dog.java 输出:

什么';这个Java属性继承的例子有什么问题? 继承.java Animal.java Cat.java Dog.java 输出:,java,inheritance,Java,Inheritance,我的动物不会说话。真可悲。字段不是多态的。您已经声明了三个完全不同的字段。。。猫和狗的影子或隐藏动物的影子 获取当前代码的最简单(但不一定是最佳)方法是从Cat和Dog中删除sound,并在构造函数中为Cat和Dog设置继承的sound字段的值 更好的方法是将动物抽象化,并为其提供一个受保护的构造函数,该构造函数接受声音。。。然后,Cat和Dog的构造函数将分别调用super(“喵喵”)和super(“woof”): public abstract class Animal { priv

我的动物不会说话。真可悲。

字段不是多态的。您已经声明了三个完全不同的字段。。。猫和狗的影子或隐藏动物的影子

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

更好的方法是将
动物
抽象化,并为其提供一个受保护的构造函数,该构造函数接受声音。。。然后,
Cat
Dog
的构造函数将分别调用
super(“喵喵”)
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");
    }
}

不能重写类字段,只能重写方法。你的
类中的
声音
字段实际上隐藏了
动物
超类中的
声音
字段

但是,您可以从子类访问超类字段,因此可以执行以下操作:

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";
  }
}

你把田地藏起来了。
动物
中的
声音
中的
声音
不同

一个可能的解决方案是创建一个构造函数,然后简单地说

super.sound = "meow";
而不是在课堂上说

protected String sound = "meow";

设置字段。

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

您是从
动物
继承的字段。您有几个选项,但最漂亮的方法是在构造函数中传递声音:

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"); }
}

通过这种方式,您可以确保一个
动物
从构造开始就始终具有有效的声音。

Java(TM)方法是在Animal.Java中声明受保护的字符串getSound(),并在子类中实现。

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

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";
    }
}
只因为猫或狗有两个“声音”,一个是从动物身上遗传下来的 隐藏而不带值(因此它打印空值);另一个是专门为猫或狗指定的值。
因此,您应该使用指针“this”来引用原始成员的“sound”。

我对只为最后一句话而向上投票感到遗憾。那么,最好的方法是什么?(你让我问了)。@macek:我正要去那里。。。只要尽可能快地输入:)如果我有几个字段要填充呢。当然,我不想要一个每个字段都有一个变量的刚性构造函数。。。对吧?呸!你在那5分钟内成功了!(再一次)@macek:那要看情况了。也许您可以在构造函数中设置所有内容,或者使用
setFoo
方法。。。这在一定程度上取决于你是否以不变性为目标。另一个选项是重写子类中的方法。视情况而定:)
super.sound = "meow";
protected String sound = "meow";
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"); }
}
public class Cat extends Animal {
//  protected String sound = "meow";

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

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

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