web-dev-qa-db-fra.com

Quel est l'intérêt d'utiliser des méthodes abstraites?

Quel est l'intérêt d'utiliser des "méthodes abstraites"? Une classe abstraite ne peut pas être instanciée, mais qu'en est-il des méthodes abstraites? Sont-ils juste là pour dire "vous devez m'implémenter", et si nous les oublions, le compilateur lance une erreur?

Cela signifie-t-il autre chose? J'ai également lu quelque chose sur "nous n'avons pas à réécrire le même code", mais dans la classe abstraite, nous "déclarons" uniquement la méthode abstraite, nous devrons donc réécrire le code dans la classe enfant.

Pouvez-vous m'aider à mieux comprendre? J'ai vérifié les autres sujets sur "classe/méthodes abstraites" mais je n'ai pas trouvé de réponse.

31
Paul

Outre le rappel que vous devez l'implémenter, le gros avantage est que toute personne qui référence l'objet par son type de classe abstraite (y compris this dans la classe abstraite elle-même) peut utiliser la méthode.

Par exemple, disons que nous avons une classe chargée de prendre l'état et de le manipuler d'une manière ou d'une autre. La classe abstraite va être chargée d'obtenir l'entrée, de la convertir en long (par exemple) et de combiner cette valeur avec la valeur précédente d'une manière ou d'une autre - cette "certaine manière" est la méthode abstraite. La classe abstraite peut ressembler à quelque chose comme:

public abstract class StateAccumulator {
    protected abstract long accumulate(long oldState, long newState);

    public handleInput(SomeInputObject input) {
        long inputLong = input.getLong();
        state = accumulate(state, inputLong);
    }

    private long state = SOME_INITIAL_STATE;
}

Vous pouvez maintenant définir un accumulateur d'addition:

public class AdditionAccumulator extends StateAccumulator {
    @Override
    protected long accumulate(long oldState, long newState) {
        return oldState + newState;
    }
}

Sans cette méthode abstraite, la classe de base n'aurait aucun moyen de dire "gérer cet état en quelque sorte". Nous ne voulons pas fournir une implémentation par défaut dans la classe de base, car cela ne signifie pas grand-chose - comment définissez-vous une implémentation par défaut pour "quelqu'un d'autre implémentera cela"?

Notez qu'il existe plus d'une façon de dépouiller un chat. Le modèle de stratégie impliquerait de déclarer une interface qui déclare le modèle accumulate et de passer une instance de cette interface à la classe de base qui n'est plus abstraite. En termes de jargon, c'est utiliser la composition au lieu de l'héritage (vous avez composé un agrégateur d'addition sur deux objets, un agrégateur et un additionneur).

16
yshavit

Supposons que vous ayez trois imprimantes pour lesquelles vous auriez besoin d'écrire un pilote, Lexmark, Canon et HP.

Les trois imprimantes auront les méthodes print() et getSystemResource().

Cependant, seule print() sera différente pour chaque imprimante. getSystemResource() reste la même sur les trois imprimantes. Vous avez également une autre préoccupation, vous souhaitez appliquer le polymorphisme.

Donc, puisque getSystemResource() est le même pour les trois imprimantes, cela peut donc être poussé jusqu'à la super classe à implémenter, en Java, cela peut être fait en faisant ce résumé dans la super classe, et en faisant une méthode abstraite dans une super classe, la classe elle-même doit également être abstraite.

public abstract class Printer{
  public void getSystemResource(){
     // real implementation of getting system resources
  }

  public abstract void print();
}

public class Canon extends Printer{
  public void print(){
    // here you will provide the implementation of print pertaining to Canon
  }
}

public class HP extends Printer{
  public void print(){
    // here you will provide the implementation of print pertaining to HP
  }
}

public class Lexmark extends Printer{
  public void print(){
    // here you will provide the implementation of print pertaining to Lexmark
  }
}

Notez que les classes HP, Canon et Lexmark ne fournissent pas l'implémentation de getSystemResource().

Enfin, dans votre classe principale, vous pouvez effectuer les opérations suivantes:

public static void main(String args[]){
  Printer printer = new HP();
  printer.getSystemResource();
  printer.print();
}
26
Oh Chin Boon

Les méthodes abstraites définissent simplement un contrat que les classes dérivées doivent implémenter. C'est ainsi que vous vous assurez qu'ils le seront toujours.

Prenons donc par exemple une classe abstraite Shape. Il aurait une méthode abstraite draw() qui devrait la dessiner. (Shape est abstrait, car nous ne savons pas comment dessiner une forme générale) En ayant la méthode abstraite draw dans Shape nous garantissons que toutes les classes dérivées, qui peuvent réellement être dessiné, par exemple Circle implémente draw. Plus tard, si nous oublions d'implémenter draw dans une classe, qui est dérivée de Shape, le compilateur aidera réellement à donner une erreur.

2
Beginner

En termes simples, en déclarant une classe "abstraite", vous appliquez un "contrat" pour les classes enfants qui en héritent, ce qui constitue un bon moyen de maintenir le "contrat".

1
Bin Feng

Si tout un résumé ne fait que déclarer des méthodes abstraites, vous avez raison, c'est un peu idiot, et une interface serait probablement supérieure.

Mais souvent, une classe abstraite implémente certaines (peut-être même toutes) des méthodes, n'en laissant que quelques-unes comme abstraites. Par exemple, AbstractTableModel. Cela évite de réécrire beaucoup de code.

Un autre "avantage" par rapport à une interface est qu'une classe abstraite peut déclarer des champs pour les sous-classes à utiliser. Donc, si vous êtes presque sûr qu'une implémentation raisonnable aurait une chaîne nommée uniqueID, vous pouvez la déclarer, ainsi que les getters/setters pertinents, dans la classe abstraite, en économisant du texte plus tard.

0
user949300

Les classes abstraites sont des classes qui contiennent une ou plusieurs méthodes abstraites. Une méthode abstraite est une méthode qui est déclarée, mais ne contient aucune implémentation. Les classes abstraites ne peuvent pas être instanciées et nécessitent des sous-classes pour fournir des implémentations pour les méthodes abstraites. Regardons un exemple de classe abstraite et une méthode abstraite.

Supposons que nous modélisons le comportement des animaux, en créant une hiérarchie de classes qui commence par une classe de base appelée Animal. Les animaux sont capables de faire différentes choses comme voler, creuser et marcher, mais il existe certaines opérations courantes comme manger, dormir et faire du bruit. Certaines opérations courantes sont effectuées par tous les animaux, mais de manière différente également. Lorsqu'une opération est effectuée d'une manière différente, elle est un bon candidat pour une méthode abstraite (forçant les sous-classes à fournir une implémentation personnalisée). Examinons une classe de base animale très primitive, qui définit une méthode abstraite pour émettre un son (comme un chien qui aboie, une vache moue ou un cochon qui coule).

public abstract Animal {

public void sleep{
// sleeping time
}
public void eat(food)
{
//eat something
}
public abstract void makeNoise();
}
public Dog extends Animal {
 public void makeNoise() {
 System.out.println("Bark! Bark!");
 }
}
public Cow extends Animal {
 public void makeNoise() {
 System.out.println("Moo! Moo!");
 }
}

Notez que le mot clé abstract est utilisé pour désigner à la fois une méthode abstraite et une classe abstraite. Maintenant, tout animal qui veut être instancié (comme un chien ou une vache) doit implémenter la méthode makeNoise - sinon il est impossible de créer une instance de cette classe. Regardons une sous-classe de chiens et de vaches qui étend la classe animale.

Maintenant, vous vous demandez peut-être pourquoi ne pas déclarer une classe abstraite en tant qu'interface et demander au chien et à la vache d'implémenter l'interface. Bien sûr, vous pourriez - mais vous auriez également besoin de mettre en œuvre les méthodes de manger et de dormir. En utilisant des classes abstraites, vous pouvez hériter de l'implémentation d'autres méthodes (non abstraites). Vous ne pouvez pas faire cela avec des interfaces - une interface ne peut fournir aucune implémentation de méthode.

Dans Word simple, une interface doit contenir toutes les méthodes abstraites mais aucune implémentation de méthode ou nous ne pouvons pas définir de méthode non abstraite dans l'interface, dans l'interface, toutes les méthodes doivent être abstraites mais dans la classe abstraite, nous pouvons définir à la fois la méthode abstraite et la méthode non abstraite, donc pour définir une méthode non abstraite, nous n'avons pas à définir une autre classe pour implémenter le comportement du même objet, c'est l'avantage de la classe abstraite sur l'interface.

0