2015-06-08 2 views
0

Может кто-нибудь объяснить это поведение? Это ошибка, или я пропущу что-то очевидное?Java-Access Speficier

1) Создайте 2 пакета, скажем pack1 и pack2 в том же каталоге.

2) В pack1 создать класс X

package pack1; 
import pack2.*; 
public class X 
{ 
    void eat() 
    { 
    System.out.println("X eat"); 
    } 

    public static void main(String args[]) 
    { 
    X x = new Y(); 
    x.eat(); //accessing eat() method on Instance of Y. 
    //But since eat() is not public or protected its visibility must be limited to class X 
    System.out.println("Done"); 
    } 
} 

3) Теперь в Pack2 создать класс Y

package pack2; 
import pack1.*; 
public class Y extends X 
{ 
} 

Метод поесть не должен быть доступен для класса Y, как это имеет ' default ", который ограничивает его видимость объявленного пакета (пакет X). Таким образом, этот метод не должен быть доступен в классе Y. Но когда я компилирую и выполняю этот код, он отлично работает. Разве это не является нарушением спецификатора доступа по умолчанию?

Также, если я изменил X x = новый Y() на Y x = новый Y(), компиляция завершится неудачно !!

+0

В дубликате замените 'private' на' package private' для ответа. Доступность определяется на основе статического типа выражения, к которому вызывается метод. В вашем случае 'X', а не' Y'. –

ответ

1

[EDIT]

1) Метод съедать не должен быть доступен для класса Y, как это имеет спецификатор «по умолчанию» доступа, который ограничивает его видимость пакета она объявлена ​​(пакет X). Таким образом, этот метод не должен быть доступен в классе Y.

Ответ: Вы не обращаетесь к методу ест из Y, вы обращаетесь к едят метод X. Кроме того, вы вызываете его от основных метод X, что означает, что он виден (вызов находится в пакете pack1).

не

Переместить код:

public static void main(String args[]) 
{ 
    X x = new Y(); 
    x.eat(); 
    System.out.println("Done"); 
} 

из класса X (в pack1) до класса Y (в Pack2), чтобы увидеть, что едят() больше не доступен. Вы получите сообщение об ошибке компилятора

метод поесть() от типа X не виден

2) Кроме того, если я меняю X х = новый Y() для Y х = новый Y(), то компиляция не удалась !!

Ответ: Потому что, как и прежде, метод вы обращаетесь не в классе Y, но класс X. В качестве способа поесть() имеет модификатор доступа по умолчанию, он не доступен через наследование. Итак, поскольку переменная теперь имеет тип Y (не X), вы больше не можете обращаться к этому методу.

+0

Все еще не могу понять. Верно ли, что тип ссылки определяет, доступен ли метод или нет? Разве это странно? Член доступен или не должен быть определен экземпляром, а не ссылкой. –

+0

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

+0

@SotiriosDelimanolis Обновлен мой ответ. – JamesB