web-dev-qa-db-fra.com

Pourquoi la sous-classe d'un autre package ne peut-elle pas accéder à une méthode protégée?

J'ai deux classes dans deux packages différents:

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
    }    
}

Je peux comprendre pourquoi il n'y a pas d'erreur dans l'appel de tryMeProtected() puisque Class2 voit cette méthode car elle hérite de Class1.

Mais pourquoi n'est-il pas possible pour un objet de Class2 d'accéder à cette méthode sur un objet de Class1 à l'aide de c.tryMeProtected();?

12
user2986848

Les méthodes protégées ne peuvent être que accessibles par héritage dans des sous-classes extérieures au package . Et par conséquent, la deuxième approche tryMeProtected(); fonctionne.

Le code ci-dessous ne sera pas compilé car nous n'appelons pas la version héritée de la méthode protected. 

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

Suivez ce lien stackoverflow pour plus d’explications.

13
Ankur Shanbhag

Je pense que vous comprenez mal la différence entre la visibilité package et 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 sera accessible où que vous soyez.
  • tryMeProtected sera accessible à toutes les sous-classes ET à toutes les classes du même package.
  • tryMePackage sera accessible à toutes les classes du même package (non disponibles aux classes enfants si elles sont dans un package différent)

Classe enfants dans le même package

package package1;

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

Classe enfants dans différents forfaits

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
    }    
}
8
Anthony Raymond

Vous utilisez deux packages différents et vous n'accédez pas à vos attributs parent par héritage direct, mais par une instance parent intermédiaire déclarée dans la classe enfant (similaire à la composition). => ce n'est pas ainsi que protected fonctionne. 

Seul l'héritage direct permet d'atteindre les attributs du parent protégé.

Ainsi, vous pouvez faire ceci:

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

mais jamais ceci:

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
    }    
}

En effet, il s’agit d’une particularité de protectedkeyword souvent mal comprise.

2
Mik378

Selon les méthodes de définition du modificateur d'accès protégé Java, les méthodes déclarées protégées dans une super-classe ne sont accessibles qu'aux sous-classes d'un autre package ou de n'importe quelle classe du package de la classe des membres protégés.

vous ne pouvez pas accéder à la méthode protégée en créant un objet de classe. Donc, pour accéder à la méthode protégée, vous devez étendre la superclasse (ceci explique que votre deuxième appel est correct).

1
Tushar D

Tout d'abord, vous devez comprendre deux choses:

1) La sous-classe peut accéder aux fonctions membres protected d'une classe 'X' dans le package 'Y', c'est-à-dire une classe qui l'étend (même si la sous-classe est dans le package autre que 'Y'). C'est pourquoi,

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

2) Une fonction membre protected d'une classe 'X' dans le package 'Y' n'est pas accessible par elle-même si elle se trouve dans d'autres packages.

[Une simple analogie: un oiseau dont les œufs sont gardés dans un nid 1 a volé vers un nid 2. Depuis le nid 2, il ne peut pas accéder à son œuf gardé dans le nid 1.] De même, une classe ne peut pas accéder sa fonction membre (sauf si public a été déclaré.) s'il se trouve dans l'autre package.

C'est pourquoi :

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

Il peut être réalisé de deux manières

1. Soit en faisant un objet de la classe Child puis en accédant à la méthode protégée de la classe Parent.

FORFAIT 1

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

PACKAGE2

public class Class2 extends Class1 {

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

2. Ou en appelant directement la méthode à partir de la classe Child

eg tryMeProtected(); 

0
Satyam