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();
?
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.
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)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
}
}
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 protected
keyword souvent mal comprise.
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).
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.
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();