Java中的继承概念

时间:2015-05-12 07:34:21

标签: java inheritance

这是一个相当基本的问题。但我无法理解继承的概念。

假设我有两个类,A和B都有一个test()方法,分别返回12,B继承了A类。在main方法中,我声明实例;

A a1 = new B();

并调用方法a1.test(),它将返回2。这是多态的概念。但是当我在子类中有一个方法test2()时,我无法使用与上面相同的实例声明来调用该方法。为什么会这样?

11 个答案:

答案 0 :(得分:3)

  

我不能使用与上面相同的实例声明来调用该方法。为什么会这样?

因为变量的类型是A,而类A没有方法test2()。 Java编译器只查看变量的类型以检查是否可以调用方法,它不会查看实际对象(在本例中为B)。

如果您为类使用更具体和有意义的名称,而不是AB等抽象名称,则更容易理解。我们打电话给他们AnimalBear代替:

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 !!!

因为在声明tvTV时,您说它可能不是高清电视。即使您可以看到,在这种情况下,编译器仍然尊重您的声明,它只是一台电视,您只能使用电视支持的方法。

答案 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类的方法。