Защо подклас в друг пакет няма достъп до защитен метод?

Имам два класа в два различни пакета:

package package1;

public class Class1 {
    public void tryMePublic() {
    }

    protected void tryMeProtected() {
    }
}


package package2;

import package1.Class1;

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1
        tryMeProtected();  // No error
    }    
}

Мога да разбера защо няма грешка при извикването на tryMeProtected(), тъй като Class2 вижда този метод като наследник от Class1.

Но защо не е възможно обект от Class2 да има достъп до този метод на обект от Class1 с помощта на c.tryMeProtected();?


person user2986848    schedule 13.11.2013    source източник
comment
Този код не генерира тази грешка. Методът tryMeProtected() изобщо не съществува.   -  person user207421    schedule 13.11.2013
comment
Тествахте ли това с точния код, който публикувахте? ако да, не може да работи, както каза EJP, имате две различни имена: tryMePublic и tryMeProtected   -  person CloudyMarble    schedule 13.11.2013


Отговори (7)


Защитените методи могат да бъдат достъпни само чрез наследяване в подкласове извън пакета. И следователно вторият подход tryMeProtected(); работи.

Кодът по-долу няма да се компилира, защото не извикваме наследената версия на защитен метод.

 Class1 c = new Class1();
 c.tryMeProtected(); // ERROR: tryMeProtected() has protected access in Class1

Следвайте тази връзка stackoverflow за повече обяснения.

person Ankur Shanbhag    schedule 13.11.2013
comment
отвън или в една опаковка (разбира се и двете), не само отвън - person Mik378; 13.11.2013
comment
В същия пакет те са достъпни чрез отделен екземпляр, тъй като има същата видимост като по подразбиране в java (с изключение на подкласове, които могат да наследяват дори извън пакета). - person Ankur Shanbhag; 13.11.2013
comment
Да, съгласен съм, бих предпочел изречение като: Наследяването на protected метода има смисъл само с различни пакети. ;) - person Mik378; 13.11.2013
comment
@Mik378 : Да, правилно. Промених изявлението в публикацията. Благодаря ви, че го посочихте. :-) - person Ankur Shanbhag; 13.11.2013

Вярвам, че не разбирате разликата между видимостта на package и protected.

package package1;

public class MyClass1 {
    public void tryMePublic() { System.out.println("I'm public"); }
    protected void tryMeProtected() { System.out.println("I'm protected"); }
    void tryMePackage() { System.out.println("I'm package"); }
}
  • tryMePublic ще бъде достъпен където и да сте.
  • tryMeProtected ще бъде достъпен за всеки подклас И всеки клас в същия пакет.
  • tryMePackage ще бъде достъпен за всеки клас в един и същ пакет (не е наличен в клас деца, ако са в различен пакет)

Детски клас в същия пакет

package package1;

public class Class2 extends MyClass1 {
    public void doNow() {
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // OK
    }    
}

Детски клас в различен пакет

package package2;

import package1.MyClass1;

public class Class3 extends MyClass1 {
    public void doNow() {
        MyClass1 c = new MyClass1();
        c.tryMeProtected() // ERROR, because only public methods are allowed to be called on class instance, whereever you are
        tryMePublic(); // OK
        tryMeProtected(); // OK
        tryMePackage(); // ERROR
    }    
}
person Anthony Raymond    schedule 28.04.2016

Използвате два различни пакета и нямате достъп до вашите родителски атрибути чрез директно наследяване, а чрез междинен родителски екземпляр, деклариран в дъщерния клас (подобно на композицията). => това не е начинът, по който protected работи.

Само директното наследяване позволява достъп до защитените родителски атрибути.

По този начин можете да направите това:

public class Class2 extends Class1 {
    doNow() {
        tryMeProtected();  // No error since direct inheritance 
    }    
}

но никога това:

public class Class2 extends Class1 {
    doNow() {
        Class1 c = new Class1();
        c.tryMeProtected(); // this is not a direct inheritance! since `c`, although a parent one is an intermediate instance created in the child instance. => bad
    }    
}

Наистина, това е особеност на protectedkeyword, която често се разбира погрешно.

person Mik378    schedule 13.11.2013
comment
@CloudyMarble Разбира се, но същността на концепцията за наследяване със защитена ключова дума е за различни пакети. В противен случай обхватът на пакетите по подразбиране би бил достатъчен. Разбира се: който може повече, може и по-малко - person Mik378; 13.11.2013

На първо място, трябва да разберете две неща:

1) protected членските функции на клас 'X' в пакет 'Y' могат да бъдат достъпни от подкласа, т.е. клас, който го разширява (дори ако подкласът е в пакет, различен от 'Y'). Защото,

tryMeProtected(); // Showed no error because this was called by class 2 that is the subclass.

2) Функция член protected от клас 'X' в пакет 'Y' не може да бъде достъпна сама по себе си, ако е в други пакети.

[ Проста аналогия: Птица, чиито яйца се съхраняват в гнездо 1, е отлетяла до гнездо 2. От гнездо 2 тя няма достъп до яйцето си, съхранявано в гнездо 1.] По същия начин клас няма достъп до своята членска функция (освен ако публично деклариран.) ако е в другия пакет.

Защото :

c.tryMeProtected();  // Showed error because this was called by class 1 reference.
                     //  You can also think of it as class 1 cannot inherit itself.
person Dewansh Nigam    schedule 06.08.2018

Съгласно методите за дефиниране на модификатор на защитен достъп на Java, които са декларирани като защитени в суперклас, могат да бъдат достъпни само от подкласовете в друг пакет или всеки клас в пакета на класа на защитените членове.

не можете да получите достъп до защитен метод чрез създаване на обект от клас. Така че за достъп до защитен метод трябва да разширите суперкласа. (това обяснява, че второто ви извикване е правилно)

person Tushar D    schedule 13.11.2013

Може да се постигне по два начина

1. Или чрез създаване на обект от клас Child и след това достъп до защитения метод на клас Parent.

ПАКЕТ 1

public class Class1 {
    protected void m1() {
        System.out.println("m1 called");
    }
}

ПАКЕТ2

public class Class2 extends Class1 {

    public static void main(String[] args) {
        Class2 class2 = new Class2();
        class2.m1();
    }
}

2. Или чрез директно извикване на метода от клас Child

eg tryMeProtected();

person Satyam    schedule 04.02.2014

защитеният модификатор е 1.Package Private 2.може да се види от подкласове от други пакети. сега ключовата разлика между:

MyClass1 c = new MyClass1();
    c.tryMeProtected();

и

tryMyProtected(); 

е, че препратката MyClass1 се използва, а не наследяване. MyClass1 е в различен пакет и този код не наследява от MyClass1.

person Nora alshareef    schedule 29.03.2020