从超类调用子类方法

Posted

技术标签:

【中文标题】从超类调用子类方法【英文标题】:Calling a subclass method from superclass 【发布时间】:2012-04-18 18:43:03 【问题描述】:

我正在学习 Java 入门课程,我们刚刚开始学习继承。我正在处理一项任务,要求我们创建一个带有名称和年龄的“宠物”超类;和三个子类,每个子类都有自己独特的特征(我选择了“狗”、“猫”和“鸟”)。在我们构建完所有这些之后,我们将创建一个 Main 类来测试所有内容,这就是我遇到问题的地方。我试图为Main 中的这些独特特征调用get 方法,但它似乎只能找到超类中的方法。

这是主类:

public class Kennel 
    public static void main(String[] args) 
        // Create the pet objects
        Pet cat = new Cat("Feline", 12, "Orange");
        Pet dog = new Dog("Spot", 14, "Dalmation");
        Pet bird = new Bird("Feathers", 56, 12);

        // Print out the status of the animals
        System.out.println("I have a cat named " + cat.getName()
                + ". He is " + cat.getAge() + " years old."
                + " He is " + cat.getColor()
                + "When he speaks he says " + cat.speak());
        System.out.println("I also have a dog named " + dog.getName()
                + ". He is " + dog.getAge() + " years old."
                + " He is a " + dog.getBreed()
                + " When he speaks he says " + dog.speak());
        System.out.println("And Finally I have a bird named " 
                + bird.getName() + ". He is " + bird.getAge() + " years old."
                + " He has a wingspan of " + bird.getWingspan() + " inches."
                + " When he speaks he says " + bird.speak());       
    

这是我的超类

abstract public class Pet 
    private String name;
    private int age;

    // Constructor
    public Pet(String petName, int petAge) 
        this.name = petName;
        this.age = petAge;
    

    // Getters
    public String getName()  return(this.name); 
    public int getAge()  return(this.age); 

    // Setters
    public void setName(String nameSet)  this.name = nameSet; 
    public void setAge(int ageSet)  this.age = ageSet; 

    // Other Methods
    abstract public String speak();

    // toString
    @Override
    public String toString() 
        String answer = "Name: " + this.name + " Age: " + this.age;
        return answer;
    

这是其中的一个子类(它们看起来都一样,并且有相同的错误)

public class Cat extends Pet 
    private String color;

    // Constructor
    public Cat(String petName, int petAge, String petColor) 
        super(petName, petAge);
        this.color = petColor;
    

    // Getters
    public String getColor()  return(this.color); 

    // Setters
    public void setColor(String colorSet)  this.color = colorSet; 

    // Other Methods
    @Override
    public String speak()  return "Meow!";  

    // toString
    @Override
    public String toString() 
        String answer = "Name: " + super.getName() + " Age: "+super.getAge()
                + " Color: " + this.color;
        return answer;
    

所以发生的事情是我无法通过 main 方法找到 cat.getColor() 方法或任何其他子类独有的方法。

【问题讨论】:

【参考方案1】:

您还可以将这些空方法添加到您的 Pet 类中:

public String getColor()  
public String setColor()  
public String speak()  

这样,您可以从 Pet 对象调用此方法,而无需将其强制转换为 Cat。一旦被调用,Cat 的方法就会覆盖超类中的方法。 这个技巧的缺点是您必须在超类中为您打算从子类调用的每个方法声明一个空方法,如果要添加多个方法,这可能会变得混乱。因此,仅对将在许多不同子类中使用的方法执行此操作。

【讨论】:

【参考方案2】:

在这里,您尝试使用作为子类方法的构造函数 (Cat) 创建超类类型 object(cat),这是不可能的。这违反了继承规则。

Pet cat = new Cat("Feline", 12, "Orange");

【讨论】:

【参考方案3】:

当你声明一个变量具有超类的类型时,你只能通过该变量访问超类​​的(公共)方法和成员变量。

Pet cat = new Cat("Feline",12,"Orange"); 
cat.getName(); // this is OK
cat.getColor(); // this is not OK, getColor() is not in Pet

要访问具体类(本例中为Cat)中的方法,您需要将变量声明为派生类

Cat cat = new Cat("Feline",12,"Orange"); 
cat.getName(); // OK, getName() is part of Cat (and the superclass)
cat.getColor(); // OK, getColor() is part of Cat

或将其转换为您知道/怀疑是具体类型的类型

Pet cat = new Cat("Feline",12,"Orange"); 
((Cat)cat).getName(); // OK (same as above)
((Cat)cat).getColor(); // now we are looking at cat through the glass of Cat

您甚至可以将这两种方法结合起来:

Pet pet = new Cat("Feline",12,"Orange"); 
Cat cat = (Cat)pet;
cat.getName(); // OK
cat.getColor(); // OK

【讨论】:

删除了我的,因为这是更完整和完全正确的版本。 这救了我的命 我们不能访问超类的受保护方法和成员变量吗? @Beginner 你可以,但只能在子类中。上面的示例假设从外部访问(例如,不相关的类或非成员函数)【参考方案4】:

当你这样做时:

 Pet cat = new Cat("Feline",12,"Orange");

编译器将变量 cat 视为 Pet。所以不能使用 Cat 类的具体方法。

您必须将 cat 声明为 Cat 类型才能解决您的问题。

问候。

【讨论】:

【参考方案5】:
Pet cat = new Cat("Feline",12,"Orange");
^^^
This is the error.

Pet 没有名为 getColor() 的方法

你需要做的:

Cat cat = new Cat(...);

【讨论】:

以上是关于从超类调用子类方法的主要内容,如果未能解决你的问题,请参考以下文章

Python子类方法从超类方法继承装饰器

当子类使用Object变量实例化时,无法从超类访问方法

无法从超类访问 Django 模型的子类

从超类中获取子类的名称

子类是不是从超类继承私有实例变量

从超类列表中提取给定子类的元素