有 Java 编程相关的问题?

你可以在下面搜索框中键入要查询的问题!

java继承不允许我创建子类的对象?

   class Animal {

    String type;
    int size;

    public Animal(String name, int size)
    {
        this.type = name;
        this.size = size;
    }

    public Animal ()
    {

    }

    public void run() {
        System.out.println("I can run!");
    }

}


class Cat extends Animal {

    String color;

    public void meow() {
        System.out.println("I can meow!");
    }

}

public class HelloWorld{

     public static void main(String []args){

        Animal cat = new Cat();

        cat.meow();
        cat.run();

     }
} 

为什么当我试图从超类动物创建一个新的Cat对象时,我的。meow()是代码的一部分。特别是“错误:找不到符号cat.meow();”。我不是在创建一个Cat对象,所以它不应该访问其中的方法吗


共 (2) 个答案

  1. # 1 楼答案

    Animal cat = new Cat()

    编译器“忘记”您创建了一个Cat实例

    您的源代码显示:我有一个名为cat的变量,它是Animal的一个实例

    在Animal类上没有meow()方法

    如果要调用子类方法,则需要一个子类实例:

    Cat cat = new Cat();
    cat.meow();
    

    或者你需要施展。基本上你告诉编译器:“我比你知道得多”

    Animal cat = new Cat();
    ( (Cat) cat).meow();
    

    关键是:java是静态类型的。在python中,解释器只会查看catthingy是否有一个名为meow()的方法,它可以调用该方法。在Java中不是这样的

  2. # 2 楼答案

    Animal是基类。如果扩展Animal,可以在该类中添加额外的方法和实例变量,这实际上是正确的

    只要实例化一个子类(扩展基类的类,例如:new Cat()),但将其分配给基类的类型(Animal),您就只能调用那里可用的方法,也就是说,在您的情况下,您只能调用在Animal类中声明的方法

    假设您有一个类Animal

    public class Animal {
      public void makeSound() {
        System.out.println("Default sound");
      }
    }
    
    

    现在创建一个类Cat,它扩展了Animal

    public class Cat extends Animal {
      private int catProperty = 5;
    
      //Override method of base class
      public void makeSound() {
        System.out.println("Meow");
      }
    
      public int getCatProperty(){
        return this.catProperty;
      }
    }
    

    另一个名为Dog的类扩展了Animal

    public class Dog extends Animal {
      private int dogProperty = 8;
    
      //Override method of base class
      public void makeSound() {
        System.out.println("Woof");
      }
    
      public int getDogProperty(){
        return this.dogProperty;
      }
    }
    

    由于Animal是基类,现在可以创建一个array of type Animal来保存CatsDogs

    Animal[] animals = new Animal[2];
    animals[0] = new Cat();
    animals[1] = new Dog();
    
    for (Animal animal : animals) {
      animal.makeSound();
    }
    

    每个animalsCatDog)现在将打印正确的声音。 如果你真的需要调用一个子类特定的方法,你必须将对象转换回该子类的一个实例。在这种情况下,您必须确定子类是什么类型

    例如:

    for (Animal animal : animals) {
      // Calls overriden method
      animal.makeSound();
      // This is illegal. Method getCatProperty is not declared in Animal  
      animal.getCatProperty();
      // This is illegal. Method getDogProperty is not declared in Animal class
      animal.getDogProperty();
    
      /*
       * IF YOU HAVE TO CALL CHILD CLASS SPECIFIC METHODS, DO IT LIKE THIS:
       */
    
      // Checks if animal is of type Cat
      if (animal instanceof Cat) {
        // Casts animal to instance of Cat
        Cat cat = (Cat) animal;
        // Calls specific Cat instance method
        System.out.println(cat.getCatProperty());
      }
    
      // Checks if animal is of type Dog
      if (animal instanceof Dog) {
        // Casts animal to instance of Dog
        Dog dog = (Dog) animal;
        // Calls specific Dog instance method
        System.out.println(dog.getDogProperty());
      }
    }
    

    正如旁注:如果你不打算直接创建Animal(Animal a = new Animal())的实例,你应该将类本身和应该被子类覆盖的方法声明为abstract

    public abstract class Animal {
      public abstract void makeSound();
    }
    
    

    此外,如果基类只有方法,而子类没有可用的实例变量,那么最好使用接口,而不是(abstract)类

    public interface Animal {
      public abstract void makeSound();
    }
    

    然后,接口必须由具体类implemented(而不是extended)创建

    public class Cat implements Animal {
      public void makeSound() {
        System.out.println("Meow");
      }
    }
    

    希望这有帮助