Object 使用超类而不是子类初始化对象

Object 使用超类而不是子类初始化对象,object,inheritance,declaration,Object,Inheritance,Declaration,我最近看到了这个示例代码,我不知道如何才能轻松找到这个问题的答案。在代码中,Dog对象、Cow对象和Snake对象都声明为Animal对象。那么,使用更通用的类声明对象是否有效?例如,我是否可以将任何对象声明为对象(因为所有类都是对象类的子类)?声明具体或更一般的优点/缺点是什么?这一切都是为了便于阅读吗 class Animal { void whoAmI() { System.out.println("I am a generic Animal."); } } class D

我最近看到了这个示例代码,我不知道如何才能轻松找到这个问题的答案。在代码中,Dog对象、Cow对象和Snake对象都声明为Animal对象。那么,使用更通用的类声明对象是否有效?例如,我是否可以将任何对象声明为对象(因为所有类都是对象类的子类)?声明具体或更一般的优点/缺点是什么?这一切都是为了便于阅读吗

class Animal {
  void whoAmI() {
    System.out.println("I am a generic Animal.");
  }
}
class Dog extends Animal {
  void whoAmI() {
    System.out.println("I am a Dog.");
  }
}
class Cow extends Animal {
  void whoAmI() {
    System.out.println("I am a Cow.");
  }
}
class Snake extends Animal {
  void whoAmI() {
    System.out.println("I am a Snake.");
  }
}

class RuntimePolymorphismDemo {

  public static void main(String[] args) {
    Animal ref1 = new Animal();
    Animal ref2 = new Dog();
    Animal ref3 = new Cow();
    Animal ref4 = new Snake();
    ref1.whoAmI();
    ref2.whoAmI();
    ref3.whoAmI();
    ref4.whoAmI();
  }
}
The output is

I am a generic Animal.
I am a Dog.
I am a Cow.
I am a Snake.

您可以用对象实例化其他每个类,但不能实例化原语,即使它们有包装器使它们成为类

这不是很好的面向对象实践,因为您希望程序尽可能地具有故障安全性

在这些类中放入更多不同的方法,这时您就开始看到问题所在

假设狗也有方法chewButt()

没问题。但这不是你能做的全部

Animal dog = new Cow();
这就汇编了

dog.chewButt();
现在我们有一个问题。牛够不着它的屁股

您希望在声明超类时尽可能严格,但要足够宽松,以便快速完成工作。你想要放松的一个原因是这样的

狗和蛇有点太不一样了。我要创造一个新的哺乳动物亚类,从动物延伸而来。我把狗、牛和其他东西放在里面

现在我可以放心,我可以做到:

Mammal mouse = new Mouse();
mouse.suckleYoung();
cat.suckleYoung();
whale.suckleYoung();
但如果我不小心尝试:

Mammal snake = new Snake();
我希望编译器在我陷入编码漏洞之前马上抱怨

我希望这有帮助。经验肯定会很快在你的大脑中燃烧这些点

编辑:引用注释:我仍然不明白为什么我不总是像“dog dog=new dog();”那样声明我的dog对象;而不是在示例代码“Animal dog=new dog()”中如何声明


这是因为你在狗身上工作的功能也可以保证与所有动物(狗、猫、蜥蜴)一起工作。如果你选择另一种方法,你将不得不为每一类动物编写一个单独的函数。更糟糕的是,你所做的每一个函数都会有相同的代码。相反,在动物中编写一次方法,每个扩展类都有一组方法。想象一下,你已经意识到你编写的方法是稍有错误,您必须更改一行,但您必须在每个动物的模块中执行此操作,因为您没有花时间创建动物超类。

从方法中得到了笑声哈哈。我仍然不明白为什么我不会总是像“dog dog=new dog()那样声明我的dog对象;与示例代码“Animal dog=new dog()中的情况比较;“.用Animal声明更一般的方法有什么意义?有什么好处我不知道吗?我发现了另一个问题,所以回答了我的问题:那么你声明对象的类型决定了你可以使用什么方法和字段。嗯,但是现在我又一次困惑了b/c为什么上面的代码示例中没有输出?”我是一个泛型动物“每次对于每个ref#实例?它们应该只能访问动物类中的方法,因为它们被声明为动物而不是更具体的动物名称(狗、牛、蛇),对吗?不。他们可以访问他们的动物类方法和他们自己的类方法。无论你如何实例化它们。无论你在“新”之后放什么“确定他们有权访问的内容。Dog扩展了Animal,因此它具有Animal的所有属性以及Dog特有的属性。请继续查看关于遗传和多态性的文档。一个接一个直到它最后发出咔嗒声。()是一个好的开始。
Mammal snake = new Snake();