Наследование не позволяет мне создать объект подкласса? - PullRequest
0 голосов
/ 11 ноября 2019
   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 из суперкласса Animal, я получаю сообщение об ошибке с частью кода .meow (). В частности, «ошибка: не удается найти символ cat.meow ();»,Разве я не создаю объект Cat, поэтому не должен ли он иметь доступ к тамошним методам?

Ответы [ 2 ]

2 голосов
/ 11 ноября 2019

Animal - базовый класс. Если вы расширили Animal, вы можете добавить дополнительные методы и переменные экземпляра в этот класс, что вы на самом деле сделали правильно.

Как только вы создадите экземпляр дочернего класса (класса, который расширяет базовый класс, например: * 1005)*) но назначив его типу базового класса (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, который содержит Cats и Dogs.

Animal[] animals = new Animal[2];
animals[0] = new Cat();
animals[1] = new Dog();

for (Animal animal : animals) {
  animal.makeSound();
}

Каждый из animals (Cat и Dog) теперь будет печатать правильный звук. Если вам действительно нужно вызвать специфичный для дочернего класса метод , вам нужно привести объект обратно к экземпляру этого дочернего класса . В этом случае вы должны быть уверены в том, какого типа является дочерний класс.

Например:

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

Так же, как sidenote: Если вы не планируете напрямую создавать экземпляры 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");
  }
}

Надеюсь, это поможет!

2 голосов
/ 11 ноября 2019

Animal cat = new Cat ()

Компилятор "забывает", что вы создали Cat экземпляр.

Ваш исходный код говорит:У меня есть переменная с именем cat, которая является экземпляром Animal.

В классе Animal нет метода meow().

Если вы хотите вызвать метод подкласса,вам нужен подкласс экземпляр:

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

или вам нужно cast . В основном вы говорите компилятору: «Я знаю лучше, чем вы».

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

Дело в том, что java статически типизирован. В python интерпретатор будет просто видеть, есть ли у этого cat вещь метод с именем meow(), который он может вызвать. Так не работает в Java.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...