我是java的新手,所以这个问题似乎对某些人有明显的答案,但它给了我一些麻烦。
如果我有
ClassA
和ClassB
和
ClassB extends ClassA
此代码中发生了什么?
public class ClassB extends ClassA{
public void foo(){
ClassA CA = new ClassB();
}
}
从这里开始,我可以通过ClassA
<来自CA
来调用方法 - 这部分是有意义的..
但我迷失了......
为什么我会这样做,重点是什么,实际发生了什么。
感谢。
答案 0 :(得分:1)
为什么我会这样做,重点是什么
您希望这样做的通常情况是,创建对象的代码和使用该对象的代码不在同一个方法/类/模块中,但需要稍微解耦。
使用多态/继承,您可以为类的用户定义接口(在您的情况下为ClassA
),并且能够在不同的实现之间切换(例如在您的情况下为ClassB
)调用需要知道的代码。
规范示例是使用集合执行某些操作的方法。集合是一个接口,有许多不同的实现。调用代码可以对Collection执行某些操作(例如迭代元素),而无需知道它是ArrayList还是HashSet。
实际发生了什么。
运行时系统似乎是您调用方法的对象实例是ClassB
的实例,并且它将代码分派到正确的位置。这是在没有调用代码需要知道它的情况下完成的。对于调用者来说,重要的是实现它想要拥有的接口(ClassA
)中定义的所有方法(Java编译器确定)。
答案 1 :(得分:1)
我通过动物的例子教授多态性。在实践中并没有多大意义,但理解这些原则是很好的。
首先是正确的方法:
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);
}
donald
和lassie
都可以eat()
和sleep()
,因为它们都是Animal
。他们每个人都发出自己的声音,他们可以被塞在一起,因为他们都是Animal
。
计数器示例将遵循以下代码:
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 */};
}
现在你不能将它们放在同一个容器中,因为它们是不同的类型。此外,您必须编写两次相同的代码(eat
和sleep
)。
答案 2 :(得分:1)
ClassA 是抽象类时没有实现某些功能的 ClassB 和此类继承的另一种用法其他一些 ClassC 是具体类,它们扩展了ClassA。
在这种情况下,ClassA实现了ClassB和ClassC的通用行为,并且这两个类添加了它们所需的功能。
让我们添加一个例子: ClassA 是 Car ,它可以开车,转弯和停止。所有这些动作都在Car中实现,但它是一辆抽象的汽车。
ClassB 是 SportsCar ,它添加了“Race”的功能。
ClassC 是 Batmobile ,如果“从头灯拍摄火箭”,它会添加功能。
所以,在这个示例中,您实现了驱动器,仅转动和停止 一次 , 并在继承类中添加其他功能。