2015-07-12 3 views
4

С помощью этого кода:Почему частный метод вызывается в суперконтексте?

public abstract class A { 
    private String runNow() { 
     return "High"; 
    } 

    public abstract String cos(); 

    static class B extends A { 
     public String runNow() { 
      return "Low"; 
     } 

     public String cos() { 
      return "cos from B"; 
     } 
    } 

    public static void main(String args[]) { 
     A[] a = new B[] {new B(), new C()}; 
     for (A aa : a) { 
      System.out.println(aa.runNow() + " " + aa.cos()); 
     } 
    } 
} 

class C extends A.B { 
    public String runNow() { 
     return "Out"; 
    } 

    public String cos() { 
     return "cos from C"; 
    } 
} 

Почему runNow метод из класса A испробованы и не из подклассов?

+1

Возможный дубликат [Переопределение личных методов в Java] (http://stackoverflow.com/questions/2000137/overriding-private-methods-in-java) – Tom

+1

Прочтите дублированный вопрос о том, почему вы не можете переопределить частный методы. И в следующий раз: аннотируйте свои методы с помощью '@ Override', чтобы компилятор мог проверить, не перепутали ли вы метод или нет. – Tom

+1

, пожалуйста, не редактируйте свой вопрос, чтобы ввести синтаксические ошибки. Вы не можете назвать свой 'A []' массив 'aa'. – Tom

ответ

2

Короткий ответ «потому что runNow() is private».

При компиляции этого вызова aa.runNow() компилятор видит, что class A имеет runNow метод, который является частным, и что ваш код вызова этого частного метода. Поскольку частные методы не могут быть переопределены, компилятор направляет вызов на метод ArunNow() - единственный, который, как он знает, существует в этом контексте.

Тот факт, что B и C также представляют свои методы с тем же именем, не имеет значения для компилятора, поскольку эти методы являются новыми в подклассах. Компилятор не может считать их переопределениями без нарушения инкапсуляции class A, который назначил runNow частным методом.

1

Это потому, что runNow() является частным методом в классе A. Частные методы не наследуются, поэтому их нельзя переопределить.

private String runNow(){ 
     return "High"; 
} 

А также, что вы создали ссылку типа А

A[] a=new B[]{new B(),new C()}; 

поэтому единственный runNow(), который будет вызываться для завершения вызова имеет класс А, как компилятор не знает о runNow() в классах B и C

1

Это потому, что метод runNow() в классе A является закрытым, поэтому в классах B и C вы не переопределяете его. И когда вы вызываете метод aa.runNow() он вызывается непосредственно из класса А.

Попробуйте сделать некоторый эксперимент и изменить свой метод в классе А к этому:

private String runNow2() { 
    return "High"; 
} 

public String runNow() { 
    return "High"; 
} 

изменить Также ваш System.out к этому один:

System.out.println(aa.runNow() + " " + aa.cos() + " " + aa.runNow2()); 

Теперь результат будет таким, как ожидалось.

Надеюсь, это поможет!

1

Почему метод runNow из класса А испробованы и не из подклассов

private методы не наследуются в подклассах. Поэтому их нельзя переоценить. Поскольку runtime-polymorphism применяется только к методам переопределения, всегда будет вызываться метод runNow от A. Измените метод runNow в A на метод public, и вы получите желаемый результат, так как методы public наследуются и могут быть переопределены.

1

Как вы уже сказали, проблема в том, что runNow() является закрытым.Поэтому он не переопределяется, и доступ к нему через ссылку типа A приведет вас к определению класса A, тогда как попытка получить к нему доступ через ссылку B получит подклассы.

Я хотел бы отметить, однако, что это «нечетный» поведение возможно только потому, что метод, который делает все это (ваш метод main) определяется внутри A. Если ваш метод main был в другом классе, который имеет доступ к этим классам, вы получите сообщение об ошибке, указывающее, что метод недоступен. Если вы подумаете об этом, вам может быть более понятно, почему методы runNow() в B и C не переопределяют значение в A. С точки зрения какого-либо объекта вне А вообще нет метода runNow() - это деталь реализации, а не часть договора A. Поэтому его нельзя переопределить, а runNow() в B и C - это только новые методы, к которым у вас нет доступа, когда вы используете B и C полиморфно, как A.

Смежные вопросы