理解Java中的继承

时间:2017-07-21 21:46:39

标签: java inheritance

如果我的问题很愚蠢,请不要生气。)

我有一段代码:

public class LinkageTest { 

public static class Parent { 

    public void test() { 
        System.out.println("parent::test"); 
    } 
} 

public static class Child extends Parent { 

    public void test() { 
        System.out.println("child::test"); 
    } 
} 

public static class Tester { 

    public void test(Parent obj) { 
        System.out.println("Testing parent..."); 
        obj.test(); 
    } 

    public void test(Child obj) { 
        System.out.println("Testing child..."); 
        obj.test(); 
    } 
} 

public static void main(String[] args) { 
    Parent obj = new Child(); 
    Tester t = new Tester(); 
    t.test(obj); 
} 

}

当我运行它时,会打印下一个字符串:

Testing parent... child::test

如果我们有test的实例,我无法理解为什么调用Parent Child方法?有人可以帮我吗?

5 个答案:

答案 0 :(得分:3)

1)类Child重新定义(覆盖)test方法。 (多态性)

2)在Tester课程中,test(Parent obj)test(Child obj)方法已超载。调用方法时,将选择具有相应类型的方法。

3)在t.test(obj)时,变量obj具有明确定义的Parent类型,因此将选择适当的方法并且"测试父级...& #34;打印。

4)在obj.test()时,将调用Child类的测试方法,因为这是一个多态性

答案 1 :(得分:1)

您正在通过引用创建儿童的对象,例如

Parent obj = new Child(); // obj has Child and Parent both type
System.out.println(obj instanceof Parent); // it returns true

和孩子重写父母的测试方法,

public static class Child extends Parent{ 
    public void test(){ //overriding here
        System.out.println("child::test"); 
    } 
}

当您调用 t.test(obj)方法

    public static void main(String[] args){ 
    Parent obj = new Child();
    Tester t = new Tester();
    t.test(obj); // obj created by Parent reference  
}

所以赶上:

public void test(Parent obj){ // catches here
        System.out.println("Testing parent..."); // Here is your first output
        obj.test(); 
    }

然后obj有重写的测试方法,所以它调用

public static class Child extends Parent{ 
    public void test(){ // overridden method first priority
        System.out.println("child::test"); // Here is your second output
    } 
} 

如果更改Child类测试方法名称,则调用Parent类测试方法,输出将为

Testing parent...
parent::test

答案 2 :(得分:1)

因为你打电话

Parent obj = new Child();
t.test(obj); //object created by Parent reference

此obj来自 parent ,因此它将从Tester类调用“Testing parent”。

然后,感谢多态,它也会从Child类调用“child :: test”,因为它被覆盖了。

尝试致电:

Child obj = new Child();
t.test(obj);

你会看到:

"Testing child..."
"child::test"

您还应该将@Override放在Child类的test()方法上。

答案 3 :(得分:0)

那是因为您正在使用参数类型Parent调用测试器方法。但实际对象里面,具体实现的是Child。这些可能不是描述它的好词,希望你理解。

如果您已调用typeof(obj),则会返回Parent。如果您已经调试了应用程序,那么您会看到调用的方法是带有Parent参数的方法,因为您传递的类型为Parent的参数。

更具体的对象是Child(实际上你可以施放obj Child并且它可以正常工作,因为它是内部的孩子)。当你做obj.test()时,它会调用child的方法,因为它被子项覆盖。

答案 4 :(得分:0)

致电Tester.test(Parent obj)的决定是在编译时进行的。在编译期间,编译器必须选择方法签名(不是实现,而是签名)。编译器看到两个具有相同名称但签名不同的方法,它只能选择Parent签名,因为您已声明Parent obj。这就是为什么在最后的字节代码中它将呈现为

find method test(Parent) in object t and execute it

致电Child.test的决定是在运行时进行的。在编译期间,编译器只找到一个方法测试签名(尽管在Parent / Child中有两个不同的实现,签名是相同的)。因此, Tester 类中两种方法的实际实现将是:

find method test() in object obj and execute it

所以,尽管调用了Tester.test(Parent)方法,它仍然会尝试在传递的对象中找到方法测试,一旦你传递了子 - 孩子的版本将被实际执行。< / p>