2016-03-24 6 views
5

Я вызываю защищенный метод супер класса из подкласса. Почему этот метод «невидим»?Java: вызов защищенного метода супер класса из подкласса - не видно?

Я читал некоторые сообщения, такие как this one, которые кажутся противоречащими следующее:

Супер класс:

package com.first; 

public class Base 
{ 
    protected void sayHello() 
    { 
     System.out.println("hi!"); 
    } 
} 

Подкласс:

package com.second; 

import com.first.Base; 

public class BaseChild extends Base 
{ 
    Base base = new Base(); 

    @Override 
    protected void sayHello() 
    { 
     super.sayHello(); //OK :) 
     base.sayHello(); //Hmmm... "The method sayHello() from the type Base is not visible" ?!? 
    } 
} 
+4

Но он расширяет базу – rapt

+0

http://stackoverflow.com/a/19949354/868975 – Bax

+0

То же, что и этот, возможно: http://stackoverflow.com/questions/36093187/accessing-protected-member-of-static- class-in-subclass-of-the-parent # comment59830891_36093187 – aioobe

ответ

9

base - это переменная, которая не является особой по своему характеру: она не является частью иерархии классов, и через нее не доступен защищенный доступ. Несмотря на то, что sayHello имеет доступ к защищенным членам Base, он имеет этот доступ только через наследование (поскольку он не находится в одном пакете: ключевое слово protected разрешает доступ через как наследование, так и пакет, см. Таблицу в this Oracle tutorial).

Доступ разрешен через this и super, поскольку они являются частью иерархии наследования.

+3

Я думаю, что вы единственный, кто заметил, что 'base' был просто переменной. –

+2

Я думаю, что мне нужна лучшая терминология, хотя .. Я знаю, что я пытаюсь сказать, но я думаю, что есть более приемлемые термины, которые я сейчас не могу вспомнить. –

+0

Это все еще удивительно, поскольку вы можете позвонить частные методы в любом экземпляре объявленного в настоящее время класса ('this' и любого другого экземпляра, кроме' this'). Следующий код работает: 'public class A {private void b() {new A(). B(); }} ' –

-3

клавиатура защищена предназначен для просмотра в одном пакете. Если дочерний класс не относится к одному и тому же пакету, защищенные методы родителя не видны дочернему классу.

+4

Абсолютно неправильно. – Bax

+1

Надеюсь, что голосование здесь за симпатию вызывает только причину ... – ChiefTwoPencils

3

Это правильное поведение. Фактически, Java Language Specification, раздел 6.6.2-1, имеет пример, очень похожий на ваш, с комментарием, который он не должен компилировать.

Специфика доступа к защищенным членам подробно в разделе 6.6.2.1:

6.6.2.1. Доступ к защищенному члену

Пусть C будет классом, в котором объявлен защищенный член. Доступ разрешен только в пределах корпуса подкласса S от C.

Кроме того, если Id обозначает поле экземпляра или метод экземпляра, то:

Если доступ осуществляется с помощью квалифицированного имени Q.Id, где Q является ExpressionName, то доступ разрешен, если и только если тип выражения Q является S или подклассом S.

Если доступ осуществляется с помощью выражения доступа поля E.Id, где E является первичным выражением, либо с помощью вызова выражения метода E.Id(. . .), где E является первичным выражением, то доступ разрешен, если и только если тип ES или подкласс S.

Это последний абзац, который описывает, почему отказ в доступе.В вашем примере C is Base, S is BaseChild и E, тип переменной base, также является Base. Поскольку Base не является ни BaseChild, ни подклассом BaseChild, доступ запрещен.

+0

Хотя я понимаю, что это предотвращает доступ через 'base', я не вижу, как он разрешает доступ через' super'. Разве 'супер' того же типа, что и' base'? Может, я пропустил что-то в JLS? Разрешено ли в другой части JLS? Мне не удалось найти раздел, который разрешает его. –

+1

@StefanDollase Это то, что «супер» не является полем, это ключевое слово, которое позволяет вам обращаться к методам базового класса, переопределенным в вашем классе. Однако фактическая ссылка делается через 'this', а не через другую переменную. – dasblinkenlight