différence entre les modificateurs d'accès protégés et paquet-privé en Java? [dupliquer]
cette question a déjà une réponse ici:
j'ai vu divers articles sur les différences entre les modificateurs privés protégés et de paquet. Une chose que j'ai trouvé contradictoire entre ces deux postes
-
l'accès" package private " des membres n'est-il pas synonyme d'accès par défaut (no-modificateur)?
dans cette réponse acceptée dit que
protégés modificateur spécifie que le membre ne peut être consulté dans son propre paquet (package-privé) et, en outre, par une sous-classe de sa classe dans un autre paquet.
-
pourquoi le modificateur protégé se comporte-t-il différemment dans la sous-classe Java?
dans cette réponse acceptée dit que
Pour satisfaire les protégés d'accès au niveau de deux conditions doivent être remplies:
- les classes doivent être dans le même colis.
- Il doit y avoir un héritage relation.
ne sont-ils pas contradictoires? d'après ce que j'ai compris des autres articles, le premier message donne la bonne réponse que protégé == paquet-privé + sous-classe dans un autre paquet.
si cette affirmation est correcte, alors pourquoi ce code échoue avec le message d'erreur suivant sur ma sous-classe Cat à la ligne 17
The method testInstanceMethod() from the type Animal is not visible
mon code pour le super et la sous-classe sont dessous.
package inheritance;
public class Animal {
public static void testClassMethod() {
System.out.println("The class" + " method in Animal.");
}
protected void testInstanceMethod() {
System.out.println("The instance " + " method in Animal.");
}
}
package testpackage;
import inheritance.Animal;
public class Cat extends Animal{
public static void testClassMethod() {
System.out.println("The class method" + " in Cat.");
}
public void testInstanceMethod() {
System.out.println("The instance method" + " in Cat.");
}
public static void main(String[] args) {
Cat myCat = new Cat();
Animal myAnimal = myCat;
myAnimal.testClassMethod();
myAnimal.testInstanceMethod();
}
}
veuillez préciser pourquoi le code ci-dessus échoue. Cela serait très utile. Merci
3 réponses
la première réponse est fondamentalement correcte - protected
les membres sont accessibles par
- classes du même colis
- sous-classes de la classe déclarante des autres colis
Toutefois, il existe une petite astuce:
6.6.2 détails sur L'accès protégé
"Un membre protégé ou le constructeur d'un objet peut être accédé depuis l'extérieur du paquet dans lequel il est déclaré uniquement par le code qui est responsable de l'implémentation de cet objet.
cela signifie que la sous-classe d'un autre paquet ne peut pas accéder aux protected
membres d'instances arbitraires de leurs superclasses, ils ne peuvent y accéder que sur des instances de leur propre type (où type est un type d'expression de compilation, puisqu'il s'agit d'une vérification de compilation).
par exemple (en supposant que ce code est dans Cat
):
Dog dog = new Dog();
Animal cat = new Cat();
dog.testInstanceMethod(); // Not allowed, because Cat should not be able to access protected members of Dog
cat.testInstanceMethod(); // Not allowed, because compiler doesn't know that runtime type of cat is Cat
((Cat) cat).testInstanceMethod(); // Allowed
il est logique, parce que l'accès de protected
membres de Dog
par Cat
peut briser les invariants de Dog
, tandis que Cat
peut accéder à ses propres protected
membres en toute sécurité, parce qu'il sait comment assurer ses propres invariants.
règles détaillées:
6.6.2.1 accès à un membre protégé
doit être la classe dans laquelle un membre protégé m est déclaré. L'accès n'est autorisé que dans le corps D'une sous-classe S DE C. En outre, si Id indique un champ d'instance ou une méthode d'instance, alors:
- si l'accès est par un nom qualifié Q. Id, OÙ Q est un nom expressif, alors L'accès est autorisé si et seulement si le type de L'expression Q Est S ou une sous-classe de S.
- si l'accès est par une expression D'accès de champ E. Id, où E est une expression primaire, ou par une expression d'invocation de méthode E. Id(. . .), où E est une expression Primaire, l'accès est autorisé si et seulement si le type de E est S ou une sous-classe de S.
6.6.2.2 accès qualifié à un constructeur protégé
que C soit la classe dans laquelle un constructeur protégé est déclaré et que s soit la classe la plus proche dans la déclaration de laquelle l'utilisation du constructeur protégé a lieu. Puis:
- Si l'accès se fait par un constructeur de la superclasse invocation super(. . .) ou par un constructeur de superclasses qualifié invocation de la forme E. super (. . .), où E est une expression Primaire, l'accès est autorisé.
- si l'accès est par une instance de création de classe anonyme expression de la forme nouveau C(. . .){...} ou par un technicien qualifié création d'instance de classe expression de la forme E. new C(. . .){...}, où E est une expression Primaire, l'accès est autorisé.
- Sinon, si l'accès est par une simple expression de création d'instance de classe de la forme new C (. . .) ou par une expression de création d'instance de classe qualifiée de la forme E. new C(. . .), où E est une expression Primaire, l'accès n'est pas autorisé. Un constructeur protégé peut être accédé par une expression de création d'instance de classe (qui ne déclare pas une classe anonyme) seulement à partir de l'intérieur du paquet dans lequel elle est définie.
Voir aussi:
dans l'accès protégé les membres sont accessibles dans le même paquet et pour les membres de classe hérités dans un autre paquet peuvent également être accessibles.
dans package access les membres des classes d'un même paquet sont accessibles. Les membres de la classe dans d'autres paquets ne peuvent pas être consultés dans l'accès au paquet.
vous avez créé une instance Cat et l'avez moulée à son type super class i.e. Animal type. Selon le type D'Animal, sa méthode de test est visible dans le même paquet ou dans n'importe quel sous-type. Si vous n'avez pas choisi le type D'Animal, le code se compilera.
L'espoir qui aide
./Arun