Je sais que le modificateur private-package (par défaut) est censé cacher une méthode (ou un membre) pour chaque classe, à l'exception de ceux du même paquet. Cependant, j'ai découvert quelques problèmes avec ce niveau d'accès.Comportement incohérent du niveau d'accès privé du paquet
Consultez le code suivant:
// pack1/MyBaseClass.java
package pack1;
public class MyBaseClass {
/* package private */ void someMethod() {
System.out.println("MyBaseClass.someMethod");
}
}
// pack1/MyDerivedClassFromOtherPackage.java
package pack1;
import pack2.MyDerivedClassInAnotherPackage;
public class MyDerivedClassFromOtherPackage extends MyDerivedClassInAnotherPackage {
@Override
/* package private */ void someMethod() {
System.out.println("MyDerivedClassFromOtherPackage.someMethod");
// super.someMethod(); // can't compile
}
}
//pack2/MyDerivedClassInAnotherPackage.java
package pack2;
import pack1.MyBaseClass;
public class MyDerivedClassInAnotherPackage extends MyBaseClass {
// @Override // can't do this (compile error)
/* package private */ void someMethod() {
System.out.println("MyDerivedClassInAnotherPackage.someMethod");
}
}
Donc, fondamentalement, il y a une classe de base dans le paquet pack1 avec une méthode de package-privé (MyBaseClass). Une autre classe dans pack2 (MyDerivedClassInAnotherPackage) étend MyBaseClass, et elle ne peut pas remplacer la méthode package-private (pour l'instant ok: les méthodes package-private sont accessibles uniquement dans le même package). Toutefois, une autre classe dans pack1 étend pack2.MyDerivedClassInAnotherPackage, et cette fois il peut remplacer sa méthode package-private (mais il ne peut pas appeler super.someMethod()
).
Une autre chose étrange est que someMethod se comporte polymorphically pour pack1.MyDerivedClassFromOtherPackage
mais pas pack2.MyDerivedClassInAnotherPackage
. Le code ci-dessous devrait préciser ce que je veux dire:
package pack1;
import pack2.MyDerivedClassInAnotherPackage;
public class MainClass {
public static void main(String[] args) {
MyBaseClass bc = new MyBaseClass();
bc.someMethod();
System.out.println("-------------------------------------------------");
MyBaseClass otherpack = new MyDerivedClassInAnotherPackage();
otherpack.someMethod();
System.out.println("-------------------------------------------------");
MyBaseClass samepack = new MyDerivedClassFromOtherPackage();
samepack.someMethod();
System.out.println("-------------------------------------------------");
}
}
Sortie:
MyBaseClass.someMethod
-------------------------------------------------
MyBaseClass.someMethod
-------------------------------------------------
MyDerivedClassFromOtherPackage.someMethod
-------------------------------------------------
Questions relatives à ces comportements:
1. How come that pack1.MyDerivedClassFromOtherPackage is allowed to override the (package-private) method of pack2.MyDerivedClassInAnotherPackage?
2. In spite of this, why is it not possible to call super.someMethod() from pack1.MyDerivedClassFromOtherPackage?
3. Why is the class in the same package (pack1) behaving polymorphically and the one in the other package (pack2) not?
PS1 .: Je sais que je devrais poster un question à la fois sur SO, mais je pense que les trois questions doivent d'une manière ou d'une autre avoir la même cause. (Je soupçonne que, en réalité, pack1.MyDerivedClassFromOtherPackage.someFunction est prépondérant pack1.MyBaseClass.someFunction et non pack2.MyDerivedClassInAnotherPackage.someFunction. Mais ce ne serait toujours pas expliquer la deuxième question, et d'ailleurs je ne pouvais pas le confirmer.)
PS2 .: Je n'ai pas vraiment d'utilisation pour ce scénario. Je joue juste avec les cas de coin (en préparation pour l'examen OCA).
Avez-vous essayé de remplacer someMethod dans pack2.MyDerivedClassInAnotherPackage avec le modificateur 'public'? – broncoAbierto
@broncoAbierto: Je ne comprends pas votre suggestion. Si je le faisais, comment cela m'aiderait-il à comprendre le comportement du niveau d'accès paquet-privé (par défaut). (Quel est le but de la question.) – Attilio
Ma conjecture est que vous ne pouvez pas remplacer car en déclarant sa visibilité à pack2-package privé, vous restreignez son accessibilité. – broncoAbierto