这是一个相当基本的问题。但我无法理解继承的概念。
假设我有两个类,A和B都有一个test()
方法,分别返回1
和2
,B继承了A类。在main方法中,我声明实例;
A a1 = new B();
并调用方法a1.test()
,它将返回2
。这是多态的概念。但是当我在子类中有一个方法test2()
时,我无法使用与上面相同的实例声明来调用该方法。为什么会这样?
答案 0 :(得分:3)
我不能使用与上面相同的实例声明来调用该方法。为什么会这样?
因为变量的类型是A
,而类A
没有方法test2()
。 Java编译器只查看变量的类型以检查是否可以调用方法,它不会查看实际对象(在本例中为B
)。
如果您为类使用更具体和有意义的名称,而不是A
和B
等抽象名称,则更容易理解。我们打电话给他们Animal
和Bear
代替:
class Animal {
}
class Bear extends Animal {
public void growl() { ... }
}
class Cat extends Animal {
public void meow() { ... }
}
Animal a1 = new Bear();
Animal a2 = new Cat();
// Doesn't work, because not every Animal is a Bear, and not all
// animals can growl.
a1.growl();
// You wouldn't expect this to work, because a2 is a Cat.
a2.growl();
答案 1 :(得分:1)
因为变量类型是A,而类A没有方法test2():
相反,您可以使用:
A a1 = new B(); // upcasting
B b1 = (B)a1; // Downcasting a1 to type B
b1.test2(); // now you can call test2 function
答案 2 :(得分:1)
因为,您的条件的左侧决定您可以调用哪种方法,右侧确定哪些方法将是称为即可。所以在这种情况下,A类没有test2()方法。
答案 3 :(得分:1)
想象一下A =“TV”而B =“HD_TV”。
你可以说
TV tv = new HD_TV() // HD TV
和
TV tv = new TV() // ordinary TV
因为HD_TV是电视。
你可以说:
tv.show(movie)
它将显示电视上的内容,但您可以通过高清电视获得更好的画面。
你不能说:
tv.showHD(hdMovie) // Compiler error !!!
因为在声明tv
为TV
时,您说它可能不是高清电视。即使您可以看到,在这种情况下,编译器仍然尊重您的声明,它只是一台电视,您只能使用电视支持的方法。
答案 4 :(得分:0)
这是因为你将实例a1
声明为A.因为B继承了A,你可以调用A中声明的所有函数,如果它们在B中重载,它们可能有不同的含义,但是你没有任何B-only东西的访问权。
如果你熟悉它,你可以看到第一个A作为某种头文件。它声明A包含的内容,而不是查看函数是如何实现的,或者默认变量是A中的所有内容。直接结果是,您只能访问声明为字面上的所有内容。
答案 5 :(得分:0)
左侧 - 本例中为A
- 是声明的类型,它不知道子类的任何特定内容。右边 - 在这种情况下为'B' - 是实际类型,这提供了行为。
因此,这将起作用,因为声明的类型B
知道B类中可用的方法。
B b1 = new B();
b1.test2();
如果可能有a1.test2()
,那就意味着每个班级都必须知道它所拥有的每个孩子 - 包括其他图书馆中的那些孩子,当项目组装完毕时!
答案 6 :(得分:0)
当B继承A类时,A
的引用是使用B
的对象创建的,如A a1 = new B();
。
在编译时编译java编译器在类A
中查找方法可用性。
所以它允许调用方法test()
而不是test2()
。
由于test()
方法在课程A
中可用,但test2()
在课程A
中不可用。
您可以输入像((B)a1).test2()
这样创建的对象。
这将有效。
答案 7 :(得分:0)
这里a1对象的类型为A.a1指向B类型的对象。 a1是类型A对类型为B的对象的引用。
因为a1是A类,所以它只知道test(),它已经在它的类定义中声明了。如果要访问类B中声明的test2,则需要键入将a1对象强制转换回B
像
B b1 = (B)a1
b1.test2()将可访问。
答案 8 :(得分:0)
这是因为您声明了一个变量并使用了一个A的B类。编译器知道它是A但是在代码后面不知道它是B。以实际物体为例,它更容易。
例如,你有:
class Pet() {
method feed();
}
并且
class Dog() extends Pet {
method feed();
method bark()
}
如果您在另一个类中有代码:
所以如果你有代码:
Pet dogPet=new Dog();
你知道这是一只狗,因为你创建了一个实例,你可以使用:
((Dog)dogPet).bark();
或者只是将变量声明为狗而不是宠物。
但是如果你在另一个类中有一个方法:
void someMethod(Pet aPet){
// Here you don't know if the Pet is a dog or not. So you know only that it
//can be fed but you don't know if it barks. Even if a Dog is supplied to the method
}
答案 9 :(得分:0)
在a1 = new B()
中,创建的对象的实际类型是B,但是您将其引用为超类型,因此您可以调用接受A(多态)的方法。
因此,如果在子类中重写了一个方法,a1.test()
正在执行子类的test()
。
要执行test2()
,您必须这样做:((B) a1).test2();
答案 10 :(得分:0)
有一个名为Up casting和Down casting的概念.Up-casting正在转换为超类型,而向下转换则转换为子类型。总是允许超广播,但是子广播涉及类型检查并且可以抛出ClassCastException。,请参阅示例代码:
class A{
public int test(){
return 1;
}
}
class B extends A{
public int test(){
return 2;
}
public int test2(){
return 3;
}
}
和
A a1 = new B();
a1.test2();//not possible
在这里,你不能调用B类的方法。