繁体   English   中英

Java中调用继承的方法

[英]Calling inherited method in Java

我有以下java代码,

class Animal {
    private String name="Animal";

    public String getName() {
        return name;
    }
}

class Cat extends Animal {
    private String name = "Cat";
}

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        System.out.println(cat.getName());
    }
}

运行该代码后,我得到了输出Animal ,但我认为它应该是Cat 在像这样覆盖Cat getName方法之后,我得到了Cat

@Override
public String getName() {
    return name;
}

这是因为在子类实例中调用继承的(不是覆盖的)方法就像cat.getName()等于调用super.getName() (所以我在第一种情况下得到Animal而不是Cat )? 还是因为实例变量隐藏的奇怪行为(我不太确定)?

name字段在子类中重新声明,但是在父类中实现了getName方法,将要读取的唯一字段是父类的Animal.name

在子类中声明已在超类中声明的字段总是一个坏主意,因为字段不会被“覆盖”,它们只是被隐藏。

您打算做的是以下任一操作:

重写方法:

class Animal {
    private String name="Animal";

    public String getName() {
        return this.name;
    }
}

class Cat extends Animal {
    public String getName() {
        return "Cat";
    }
}

您也可以在子类中声明一个不同的字段,但这仍然是一个坏主意。 做到这一点的“正确”方法是覆盖该方法。

或者,将字段暴露给子类,并更改子类的值:

class Animal {
    protected String name = "Animal";

    public String getName() {
        return name;
    }
}

class Cat extends Animal {
    public Cat() {
        this.name = "Cat";
    }
}

这样,就不会混淆哪个字段存储实际值,并且“覆盖”发生的位置很清楚。

在 Cat 类中添加一个同名的私有作用域变量不会掩盖 Animal 类中的变量。 要更改行为,您需要覆盖访问器方法以从 Cat 类上下文中读取变量。

您可以重载方法,而不是数据成员。 Animal.nameCat.name是两个不同的数据成员。 Animal.getName()没有什么特别之处——它返回Animal.name ,并且完全不知道Cat.name

一种可能的方法是只有一个数据成员Animal.name ,并让每个类对其进行不同的初始化。 例如:

class Animal {
    private String name;

    public Animal() {
        this("Animal);
    }

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

    public String getName() {
        return name;
    }
}

class Cat extends Animal {
    public Cat() {
        this("Cat');
    }
}

或者如果你想依赖你的类名,你可以使用getSimpleName

class Animal {
    private String name;

    public Animal() {
        name = getClass().getSimpleName();
    }

    public String getName() {
        return name;
    }
}

class Cat extends Animal {
}

这是因为cat.getName()调用Animal类中的getName()方法,该方法只知道自己的name字段,而不知道子类之一。

一个可能的解决方案可能是:

class Animal {
    private String name = "Animal";

    public String getName() {
        return name;
    }

    public void setName(String name) {
        this.name = name;
    }
}

class Cat extends Animal {
    private String name = "Cat";

    public Cat() {
        setName(name);    
    }
}

public class Test {
    public static void main(String[] args) {
        Cat cat = new Cat();
        System.out.println(cat.getName());
    }
}

我不鼓励你重写方法,因为你应该在未来的每个Animal子类上都这样做。

您需要覆盖方法 getName()。 它是实例级函数,您可以在子类中调用它,但如果不覆盖该函数,则无法修改它。 所以它使用父类属性调用父类函数。

如果您想在输出中使用“cat”,只需覆盖该方法。

接受的答案涵盖了一些很好的答案,但我想添加一些内容。

  1. 如果您正在做完全相同的事情,我不鼓励在 Cat 类中添加重写的 getName 方法。 这是为了防止您可能创建的任何其他子类中的代码重复。
  2. 您可以创建一个构造函数来初始化名称字段,并将名称字段切换为受保护。

例如。

class Animal {
    protected String name;

    public Animal() {
        this.name = "Animal";
    }

    public String getName() {
        return this.name;
    }
}

class Cat extends Animal {
    public Cat() {
        this.name = "Cat";
    }
}

  1. 或者,如果您想保持名称字段私有,您可以创建一个受保护的 setter 方法,以仅允许您的子类设置名称。

例如。

class Animal {
    private String name = "Animal";

    public String getName() {
        return this.name;
    }

    protected void setName(String name) {
        this.name = name;
    }
}

class Cat extends Animal {
    public Cat() {
        setName("Cat");
    }
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM