What's wrong with this example of Java propert

2020-03-01 08:24发布

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

Output:

null
null

My animals cannot speak. So sad.

7条回答
冷血范
2楼-- · 2020-03-01 09:10

Fields aren't polymorphic. You've declared three entirely distinct fields... the ones in Cat and Dog shadow or hide the one in Animal.

The simplest (but not necessarily best) way of getting your current code is to remove sound from Cat and Dog, and set the value of the inherited sound field in the constructor for Cat and Dog.

A better approach would be to make Animal abstract, and give it a protected constructor which takes the sound... the constructors of Cat and Dog would then call super("meow") and super("woof") respectively:

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");
    }
}
查看更多
干净又极端
3楼-- · 2020-03-01 09:13

You're shadowing the field inherited from Animal. You have a few options, but the prettiest way of doing it is passing the sound in the constructor:

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

This way, you can make sure that an Animal always has a valid sound, right from construction.

查看更多
▲ chillily
4楼-- · 2020-03-01 09:14

The Java(TM) way is to declare the protected String getSound() in Animal.java and implement it in the subclasses.

查看更多
Evening l夕情丶
5楼-- · 2020-03-01 09:19

You're hiding fields. The sound in Animal is not the same String as the sound in Cat.

One possible solution is to create a constructor and there simply say

super.sound = "meow";

instead of in the class body saying

protected String sound = "meow";

to set the field.

查看更多
Deceive 欺骗
6楼-- · 2020-03-01 09:19

You didn't allow your animals to speak! you should do like this :

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

just because there are two members "sound" in Cat or Dog,and the one inherited from Animal is hidden without value(so it prints null);another is special to Cat or Dog,which is assigned a value. So you should use the pointer 'this' to quote the original member 'sound'.

查看更多
在下西门庆
7楼-- · 2020-03-01 09:21

You cannot override class fields, only methods. The sound field in your Dog and Cat classes is actually hiding the sound field in the Animal superclass.

You can, however, access superclass fields from subclasses, so you could do something like this:

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

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

Or, you can make the Animal class abstract, and declare the speak method abstract too, then define it in subclasses:

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";
  }
}
查看更多
登录 后发表回答