Pour la programmation orientée objet, l’abstraction est l’une de ses principales caractéristiques. En Java, l’abstraction de la POO peut se manifester sous deux formes :les interfaces et les classes abstraites.Il existe de nombreuses similitudes entre les deux, ainsi que de nombreuses différences. Beaucoup de débutants pensent qu’elles peuvent être utilisées de manière interchangeable, mais en réalité ce n’est pas le cas. Aujourd’hui, découvrons ensemble les interfaces et les classes abstraites en Java.


1. Classes abstraites

Avant de comprendre les classes abstraites, commençons par comprendre les méthodes abstraites. Une méthode abstraite est une méthode spéciale : elle n’a qu’une déclaration, mais aucune implémentation concrète. Le format de déclaration d’une méthode abstraite est :

abstract void fun();

Les méthodes abstraites doivent être modifiées avec le mot-clé abstract. Si une classe contient une méthode abstraite, on l’appelle une classe abstraite, et la classe abstraite doit être précédée du mot-clé abstract. Comme une classe abstraite contient des méthodes sans implémentation concrète, vous ne pouvez pas créer d’objets à partir d’une classe abstraite.

Notez le problème suivant : dans le livre « Thinking in Java », une classe abstraite est définie comme « une classe contenant des méthodes abstraites », mais on a ensuite découvert que si une classe ne contient pas de méthodes abstraites et est seulement modifiée avec abstract, elle est aussi une classe abstraite. C’est-à-dire qu’une classe abstraite n’a pas nécessairement besoin de contenir des méthodes abstraites. Personnellement, je pense qu’il s’agit d’une question pointilleuse, car si une classe abstraite ne contient aucune méthode abstraite, pourquoi la concevoir comme une classe abstraite ? Alors retenez simplement ce concept pour l’instant, et il n’est pas nécessaire d’approfondir la raison.

[public] abstract class ClassName {
    abstract void fun();
}

On peut en déduire que les classes abstraites existent pour l'héritage. Si vous définissez une classe abstraite sans en hériter, alors vous avez créé cette classe abstraite en vain, car vous ne pouvez rien en faire. Pour une classe parente, si l'une de ses méthodes n'a pas de sens lorsqu'elle est implémentée dans la classe parente et doit être implémentée différemment selon les besoins réels des sous-classes, cette méthode peut être déclarée comme méthode abstraite, et à ce moment la classe devient également une classe abstraite.

Une classe contenant des méthodes abstraites est appelée classe abstraite, mais cela ne signifie pas qu'une classe abstraite ne peut avoir que des méthodes abstraites. Comme une classe ordinaire, elle peut aussi avoir des variables membres et des méthodes membres ordinaires. Notez qu'il existe trois différences principales entre les classes abstraites et les classes ordinaires :

  • 1) Les méthodes abstraites doivent être public ou protected (car si elles sont private, elles ne peuvent pas être héritées par les sous-classes, et les sous-classes ne pourront pas les implémenter). Par défaut, elles sont public.
  • 2) Les classes abstraites ne peuvent pas être utilisées pour créer des objets ;
  • 3) Si une classe hérite d'une classe abstraite, la sous-classe doit implémenter les méthodes abstraites de la classe parente. Si la sous-classe n'implémente pas les méthodes abstraites de la classe parente, la sous-classe doit également être définie comme une classe abstraite.
  • À d'autres égards, les classes abstraites ne sont pas différentes des classes ordinaires.

2. Interfaces

Une interface, appelée « interface » en anglais, désigne généralement en génie logiciel des méthodes ou des fonctions qui sont fournies pour que d'autres puissent les appeler. On peut en comprendre l'intention originale des concepteurs du langage Java : c'est une abstraction du comportement. En Java, la forme de définition d'une interface est la suivante :

[public] interface InterfaceName {
 
}

Les interfaces peuvent contenir des variables et des méthodes. Cependant, notez que les variables dans une interface sont implicitement spécifiées comme des variables public static final (et ne peuvent être que des variables public static final ; utiliser private provoquera une erreur de compilation), tandis que les méthodes sont implicitement spécifiées comme des méthodes public abstract et ne peuvent être que des méthodes public abstract (utiliser d'autres mots-clés tels que private, protected, static, final, etc. provoquera une erreur de compilation). De plus, aucune des méthodes d'une interface ne peut avoir d'implémentation concrète ; c'est-à-dire que toutes les méthodes d'une interface doivent être des méthodes abstraites. À partir de cela, nous pouvons vaguement voir la différence entre les interfaces et les classes abstraites. Une interface est un type extrêmement abstrait ; elle est plus « abstraite » qu'une classe abstraite, et les variables ne sont généralement pas définies dans une interface.

Pour qu'une classe implémente un ensemble spécifique d'interfaces, vous devez utiliser le mot-clé implements. Le format spécifique est le suivant :

class ClassName implements Interface1,Interface2,[....]{
}

On peut voir qu'une classe est autorisée à implémenter plusieurs interfaces spécifiques. Si une classe non abstraite implémente une interface, elle doit implémenter toutes les méthodes de cette interface. Pour une classe abstraite qui implémente une interface, elle n'est pas obligée d'implémenter les méthodes abstraites de cette interface.


Différences entre les classes abstraites et les interfaces

1. Différences syntaxiques

  • 1) Les classes abstraites peuvent fournir les détails d'implémentation des méthodes membres, tandis que les interfaces ne peuvent avoir que des méthodes public abstract ;
  • 2) Les variables membres dans les classes abstraites peuvent être de divers types, tandis que les variables membres dans les interfaces ne peuvent être que de type public static final ;
  • 3) Les interfaces ne peuvent pas contenir de blocs de code statiques ni de méthodes statiques, tandis que les classes abstraites peuvent avoir des blocs de code statiques et des méthodes statiques ;
  • 4) Une classe ne peut hériter que d'une seule classe abstraite, mais une classe peut implémenter plusieurs interfaces.

2. Différences au niveau de la conception

1) Une classe abstraite est une abstraction d'un type de chose, c'est-à-dire une abstraction d'une classe, tandis qu'une interface est une abstraction du comportement. Une classe abstraite abstrait la classe entière dans son ensemble, y compris les attributs et les comportements, mais une interface n'abstrait qu'une partie d'une classe (le comportement). Prenons un exemple simple : les avions et les oiseaux sont des types de choses différents, mais ils partagent une caractéristique commune : ils peuvent tous deux voler. Lors de la conception, vous pouvez concevoir l'avion comme une classe Airplane et l'oiseau comme une classe Bird, mais vous ne pouvez pas traiterle volcomme une classe non plus, car ce n'est qu'une caractéristique comportementale, pas une description abstraite d'un type de chose. À ce stade, vous pouvez concevoir le vol comme une interface Fly, contenant la méthode fly(), puis Airplane et Bird implémentent l'interface Fly selon leurs propres besoins. Quant aux différents types d'avions, comme les avions de chasse et les avions civils, ils peuvent hériter directement d'Airplane. De même pour les oiseaux, différents types d'oiseaux peuvent hériter directement de la classe Bird. De là, nous pouvons voir que l'héritage est une relation « est un », tandis que l'implémentation d'interface est une relation « a un ». Si une classe hérite d'une classe abstraite, alors la sous-classe doit être un type de la classe abstraite, tandis que l'implémentation d'interface concerne le fait qu'elle a ou possède une certaine capacité. Par exemple, si un oiseau peut voler (ou s'il a la caractéristique du vol) ; s'il peut voler, il peut implémenter cette interface, s'il ne peut pas voler, il n'implémente pas cette interface.

2) Les niveaux de conception sont différents. Une classe abstraite, en tant que classe parente de nombreuses sous-classes, est une conception basée sur un modèle. Une interface est une spécification comportementale, une conception radiale. Qu'est-ce qu'une conception basée sur un modèle ? L'exemple le plus simple est que tout le monde a utilisé des modèles dans PPT. Si ppt B et ppt C sont conçus à l'aide du modèle A, la partie commune de ppt B et ppt C est le modèle A. Si leur partie commune doit être modifiée, il suffit de modifier le modèle A, sans avoir à modifier à nouveau ppt B et ppt C. La conception radiale, par exemple, si un certain ascenseur est équipé d'une certaine alarme, dès que l'alarme doit être mise à jour, toutes doivent être mises à jour. Cela signifie que, pour une classe abstraite, si vous devez ajouter une nouvelle méthode, vous pouvez directement ajouter une implémentation concrète dans la classe abstraite, et les sous-classes n'ont pas besoin de changer ; mais ce n'est pas le cas pour une interface. Si l'interface change, toutes les classes qui implémentent l'interface doivent être modifiées en conséquence.

Voici l'exemple le plus largement diffusé sur Internet : l'exemple des portes et des alarmes : toutes les portes ontopen()etclose()deux actions. À ce stade, nous pouvons définir ce concept abstrait à travers des classes abstraites et des interfaces :

abstract class Door { public abstract void open(); public abstract void close(); }

Ou :

interface Door { public abstract void open(); public abstract void close(); }

Mais maintenant, si nous avons besoin que la porte ait une fonction d'alarme, comment devrions-nous l'implémenter ? Voici deux approches :

1) Mettez les trois fonctions dans la classe abstraite, mais de cette façon toutes les sous-classes héritant de cette classe abstraite auront la fonction d'alarme, alors que certaines portes pourraient ne pas nécessairement avoir la fonction d'alarme ;

2) Mettez les trois fonctions dans l'interface. Une classe qui a besoin de la fonction d'alarme devrait alors implémenter open() et close() dans cette interface, mais peut-être que cette classe n'a pas du tout les fonctions open() et close(), comme une alarme incendie.

On peut en déduire que open(), close() et alarm() de Door appartiennent en fait à des comportements de deux catégories différentes. open() et close() sont des caractéristiques comportementales inhérentes à la porte elle-même, tandis que alarm() est un comportement supplémentaire étendu. Par conséquent, la meilleure solution est de concevoir l'alarme séparément comme une interface contenant le comportement alarm(), et de concevoir Door comme une classe abstraite séparée contenant les deux comportements open et close. Concevez ensuite une classe AlarmDoor qui hérite de la classe Door et implémente l'interface Alarm.

interface Alram { void alarm(); } abstract class Door { void open(); void close(); } class AlarmDoor extends Door implements Alarm { void oepn() { //.... } void close() { //.... } void alarm() { //.... } }

Adresse d'origine : http://www.cnblogs.com/dolphin0520/p/3811437.html