web-dev-qa-db-fra.com

modificateurs d'accès java et méthodes de substitution

Pourquoi Java spécifie-t-il que le spécificateur d'accès pour une méthode de substitution peut autoriser davantage, mais pas moins, l'accès que la méthode substituée? Par exemple, une méthode d'instance protégée dans la superclasse peut être rendue publique, mais pas privée, dans la sous-classe.

54
yesilupper

C'est un principe fondamental de la programmation orientée objet: la classe enfant est une instance à part entière de la classe parent et doit donc présenter au moins la même interface que la classe parent. Rendre moins visible les objets protégés/publics violerait cette idée; vous pouvez rendre des classes enfants inutilisables en tant qu'instances de la classe parent.

61
Patrick87

Imaginez ces deux classes:

public class Animal {
  public String getName() { return this.name; }
}

public class Lion extends Animal {
  private String getName() { return this.name; }
}

Je pourrais écrire ce code:

Animal lion = new Lion();
System.out.println( lion.getName() );

Et il devrait être valide, car sur Animal la méthode getName () est publique, bien qu'elle ait été rendue privée sur Lion . Il n'est donc pas possible de rendre les choses moins visibles sur les sous-classes, car une fois que vous avez une référence de super-classe, vous pourrez accéder à ces informations.

31
Maurício Linhares

Parce que ce serait bizarre:

class A {
    public void blah() {}
}

class B extends A {
    private void blah() {}
}


B b = new B();
A a = b;
b.blah();  // Can't do it!
a.blah();  // Can do it, even though it's the same object!
7
Oliver Charlesworth

Prenons un exemple donné ci-dessous

 class Person{
 public void display(){
      //some operation
    }
 }

class Employee extends Person{
   private void display(){
       //some operation
   }
 }

Le dépassement typique se produit dans le cas suivant

Person p=new Employee();

Ici p est la référence de l'objet avec le type Person (super class) lorsque nous appelons p.display (). Le modificateur d'accès étant plus restrictif, la référence object p ne peut pas accéder à l'objet child de type Employee

7
Vineeth Bhaskaran

En retard pour le parti, mais je voudrais ajouter une autre préoccupation concernant le dépassement: la méthode de remplacement doit permettre moins (ou le même niveau d’exception jetable) que la méthode remplacée; même rien du tout jetable.

Le principe de substitution de Liskov peut aussi expliquer cela:

interface Actionable {
  void action() throws DislocationException;
}

public class Actor implements Actionable {
  @Override 
  public void action() throws DislocationException {
     //....
  }
} 

public class Stuntman implements Actionable {
  @Override // this will cause compiler error
  public void action() throws DislocationException, DeathException {
     //....
  }
}

// legacy code to use Actionable
try {
   Actionable actor = new Actor(); // this cannot be replaced by a Stuntman, 
                                   // or it may break the try/catch block
   actor.action();
} catch (DislocationException exc) {
   // Do something else
}

Ci-dessus, la méthode surchargée s'est engagée à ne plus laisser tomber l'exception DislocationException (dans le pire des cas, un médecin est nécessaire sur le lieu de tournage). Donc, la méthode prioritaire ne doit pas casser cela, en ajoutant plus DeathException (ou une ambulance est un must)

J'appelle souvent la règle dominante "[peut être] plus d'accès [niveau], [mais] moins d'exception" 

3
U and me

Parce qu'une sous-classe est une spécialisation de la super-classe, ou en d'autres termes, c'est une extension de la super-classe.

Imaginez par exemple la méthode toString. Tous les objets Java l’ont parce que la classe Object l’a. Imaginez que vous puissiez définir une classe avec la méthode toString private. Vous ne traiterez alors plus tous les objets de la même manière. Par exemple, vous ne pourriez plus le faire en toute sécurité:

for (Object obj : collection) System.out.println(obj);

0
João Fernandes

Eh bien, en ce qui concerne le cas spécifique que vous avez mentionné, comment Java traiterait-il cela exactement? Si la sous-classe a rendu une méthode publique/protégée privée, que doit faire la machine virtuelle Java lorsque cette méthode est appelée sur une instance de la sous-classe? Honorer le privé et invoquer l'implémentation de la superclasse? En outre, vous rompez le contrat spécifié par la super-classe lorsque vous dites tout à coup "personne ne peut accéder à cette méthode, malgré les termes du contrat initialement".

0
Marvo