Java 将ObjectA实例化为ObjectB是如何工作的?这里发生了什么?

Java 将ObjectA实例化为ObjectB是如何工作的?这里发生了什么?,java,class,inheritance,polymorphism,Java,Class,Inheritance,Polymorphism,我是java新手,所以这个问题似乎对某些问题有一个明显的答案,但它给了我一些麻烦 如果我有 ClassA和ClassB 及 ClassB扩展了ClassA 这段代码中发生了什么 public class ClassB extends ClassA{ public void foo(){ ClassA CA = new ClassB(); } } 从这里,我可以通过CA从ClassA调用方法 为什么我会这样做,重点是什么 通常情况下,创建对象的代码和使用对象

我是java新手,所以这个问题似乎对某些问题有一个明显的答案,但它给了我一些麻烦

如果我有

ClassA
ClassB

ClassB扩展了ClassA

这段代码中发生了什么

public class ClassB extends ClassA{

    public void foo(){
        ClassA CA = new ClassB();

    }

}
从这里,我可以通过
CA
ClassA
调用方法 为什么我会这样做,重点是什么

通常情况下,创建对象的代码和使用对象的代码不在同一个方法/类/模块中,但需要稍微解耦

通过多态性/继承,您可以为类的用户定义一个接口(在您的例子中是
ClassA
),并且能够在不同的实现之间切换(例如在您的例子中是
ClassB
),而调用代码不需要知道这一点

一个典型的例子是对集合执行某些操作的方法。集合是一个接口,有许多不同的实现。调用代码可以对集合执行某些操作(例如迭代元素),而不需要知道它是ArrayList还是HashSet

以及实际发生的情况


发生的情况是,运行时系统似乎认为您正在调用方法的对象实例是
ClassB
的实例,并且它将代码分派到正确的位置。这是在调用代码不需要知道的情况下完成的。对于调用者来说,重要的是它想要拥有的接口(
ClassA
)中定义的所有方法都被实现(Java编译器确保了这一点)。

我通过动物的例子学习多态性。在实践中,这并没有多大意义,但了解这些原则是一种很好的方式

首先,正确的方法是:

class Animal {
   public void eat() {/* code for eating */};
   public void sleep() {/* code for sleeping */};
}

class Dog extends Animal {
   public void bark() { /* code for barking */ }
}

class Duck extends Animal {
   public void quack() { /* code for quacking */ }
}
使用此代码,您可以执行以下操作:

{
   Dog lassie = new Dog();
   Duck donald = new Duck();

   lassie.eat();
   lassie.sleep();
   lassie.bark();
   donald.eat();
   donald.sleep();
   donald.quack();

   List<Animal> barn = new ArrayList<Animal>();
   barn.Add(lassie);
   barn.Add(donald);
}

现在您不能将它们都放在同一个容器中,因为它们是不同的类型。您还必须编写两次相同的代码(
eat
ing和
sleep
ing)。

ClassA中,这种继承的另一个用法是一个抽象类,它没有实现某些功能,而ClassB和其他一些ClassC是扩展ClassA的具体类

在本例中,ClassA实现了ClassB和ClassC的共同行为,这两个类添加了它们所需的功能

让我们添加一个示例: ClassA是一款汽车,它可以驾驶、转弯和停车。所有这些操作都在Car中实现,但它是一个抽象的Car

ClassB是一款跑车,它增加了“比赛”功能

ClassC蝙蝠车,它增加了“从头灯发射火箭”的功能

因此,在本例中,您只执行一次驱动、转动和停止
并在继承类中添加其他功能。

欢迎使用,但您可能希望先使用;)。。。是的,一开始它让人困惑,但它非常、非常强大,是OOP
public class TestBikes{public static void main(String[]args){bike bike01,bike02,bike03;bike01=新自行车(20,10,1);bike02=新山地自行车(20,10,5,“双”);bike03=新公路自行车(40,20,8,23);bike01.printDescription();bike02.printDescription();bike03.printDescription();}}
单击了您的第一个链接,并对其进行了精彩的解释,尤其是这一部分。谢谢。那么你能解释一下为什么我不能使用
ClassB
中的方法吗?当我使用
ClassA CA=new ClassB()
CA
时,我不能访问任何
ClassB
。据我所知,这应该是可能的。。不唯一的方法是执行
ClassB CB=new ClassB()
但是oracle的
多态性
示例显示了类似
Bycicle bike01=new MountainBike()
的内容,并且它通过
bike01
使用
MountainBike
方法,所以我很困惑。如果您的变量类型为
ClassA
,那么您可以访问
ClassA
中定义的所有方法。不多不少。编译器不知道运行时实例实际上是具有附加方法的子类类型(因为您没有这样声明它)。这就是像Java这样的类型化语言的要点。它允许编译器检查这些方法是否真的存在(与Perl或Javascript不同)。缺点是您不能(轻松地)调用编译器不知道的方法。
class Dog {
   public void bark() { /* code for barking */ }
   public void eat() {/* code for eating */};
   public void sleep() {/* code for sleeping */};
}

class Duck {
   public void quack() { /* code for quacking */ }
   public void eat() {/* code for eating same as code in Dog */};
   public void sleep() {/* code for sleeping  same as code in Dog */};
}