2017-05-30 122 views
-1

我是学生,学习Java。我知道,protected表示从childrenthe same package访问。这里我们继承并重写一个受保护的方法。在这样一个动作之后,无论基类想调用它自己的方法,它都会从子类中调用新的被覆盖的方法。我一直在调试这一段时间,并用注释标记执行顺序。但我不明白为什么当我从基类构造函数中明确调用基类方法时,它不会调用它?为什么从基类调用方法调用子方法?

public class Solution { 

    public static void main(String[] args) { 
     new B(); // first 
    } 

    public static class A { 

     public A() { 
      initialize(); // third 
     } 

     protected void initialize() { 
      System.out.println("class A"); // we never go here 
     } 
    } 

    public static class B extends A { 

     public B() { 
      super(); // second 
      initialize(); // fifth 
     } 

     protected void initialize() { 
      System.out.println("class B"); // fourth, sixth 
     } 
    } 
} 

这是从一个网站上的任务,所以基本的解决方案是将initialize方法的访问修饰符改变从protectedprivate。但我仍然不明白为什么会出现问题。

+0

我认为这只是调用覆盖的方法,因为你是从覆盖它的类调用超类,所以它总是会使用这个方法从B类? –

+0

这是整个重写... –

回答

0

作为达科他回答,根本原因是polymorphism。这意味着我们可以创建子对象,但将它们称为它们的父类型,并且当我们调用父层的方法时,我们实际上会引用子对象的方法。

在我的情况下,我创建了一个子对象(标记为//第一个)B,它有自己的initialize方法的主体。继承的一个细微差别是它不包含构造函数,所以我可以调用父类的构造函数(标记为//第二个)。在父类的构造函数中,我调用initialize方法 - 这就是多态,因为我从其父抽象层调用子方法。

这里是问题的答案 - 出现这种情况,因为我们只为B实例分配的内存,这意味着,我们采取了A作为我们基地,并开始扩展它(尽管我们可以在里面覆盖任何东西)。我们做的只有两两件事是:

  1. 我们创建了一个构造函数(这是不包括在基地,如上所述)
  2. 我们覆盖了initialize方法的代码。此对象现在丢失了位于基数内的此方法的代码。

polymorphism这个概念就是这样设计的,有没有办法让我们访问这个基地方法,除非我们专门创建一个对象,要么是A本身或不覆盖此方法的孩子。

1

你试图做的是打败多态的目的。你可以,但你必须专门打电话。给你的方法添加一个布尔值,并调用super.initialize(Boolean)。再一次地,这违背了多态性和扩展类HAS去了解超类。不是非常优雅。

public class Solution { 
    public static void main(String[] args) { 
     new B(); // first 
    } 

    public static class A { 

    public static boolean USE_SUPER = true; 

     public A() { 
      initialize(USE_SUPER); 
     } 

     protected void initialize(boolean unusedHere) { 
      System.out.println("class A"); 
     } 
    } 

    public static class B extends A { 
     public static boolean USE_EXTENDED = false; 

     public B() { 
      super(); 
      initialize(USE_EXTENDED); 
     } 

    protected void initialize(boolean useSuper) { 
     if (useSuper) 
       super.initialize(useSuper); 
     else 
       System.out.println("class B"); 
    } 
} 

    } 
+0

@SamKruglov,如果A.initialize()不同于B.initialize(),为什么使用多态?以不同的方式称呼它A.initializeA()和B.initializeB()。 – Dakoda

+0

哦,是的,我想我明白了。我们只创建了对象B,因此我们只从这个角度有方法。并且来自父项的调用方法仅意味着多态性。谢谢! – Sam