Une chose curieuse se produit en Java lorsque vous utilisez une classe abstraite pour implémenter une interface: certaines méthodes de l'interface peuvent être complètement manquantes (c'est-à-dire qu'aucune déclaration abstraite ou implémentation réelle n'est présente), mais le compilateur ne se plaint pas.
Par exemple, étant donné l'interface:
public interface IAnything {
void m1();
void m2();
void m3();
}
la classe abstraite suivante est joyeusement compilée sans avertissement ni erreur:
public abstract class AbstractThing implements IAnything {
public void m1() {}
public void m3() {}
}
Pouvez-vous expliquer pourquoi?
java
interface
abstract-class
Giulio Piancastelli
la source
la source
:w
un des fichiers.Réponses:
En effet, si une classe est abstraite, vous devez par définition en créer des sous-classes pour l'instancier. Les sous-classes seront requises (par le compilateur) pour implémenter toutes les méthodes d'interface que la classe abstraite a laissées de côté.
En suivant votre exemple de code, essayez de créer une sous-classe de
AbstractThing
sans implémenter lam2
méthode et voyez les erreurs que le compilateur vous donne. Cela vous obligera à implémenter cette méthode.la source
Parfaitement bien.
Vous ne pouvez pas instancier des classes abstraites ... mais des classes abstraites peuvent être utilisées pour héberger des implémentations courantes pour m1 () et m3 ().
Donc, si l' implémentation de m2 () est différente pour chaque implémentation mais que m1 et m3 ne le sont pas. Vous pouvez créer différentes implémentations concrètes de IAnything avec juste l'implémentation différente de m2 et dériver de AbstractThing - en respectant le principe DRY. Valider si l'interface est complètement implémentée pour une classe abstraite est futile.
Mise à jour : Fait intéressant, je trouve que C # applique cela comme une erreur de compilation. Vous êtes obligé de copier les signatures de méthode et de les préfixer avec 'abstract public' dans la classe de base abstraite dans ce scénario. (Quelque chose de nouveau tous les jours :)
la source
C'est très bien. Pour comprendre ce qui précède, vous devez d'abord comprendre la nature des classes abstraites. Ils sont similaires aux interfaces à cet égard. C'est ce que dit Oracle à ce sujet ici .
Il faut donc réfléchir à ce qui se passe lorsqu'une interface étend une autre interface. Par exemple ...
... comme vous pouvez le voir, cela compile également parfaitement bien. Tout simplement parce que, tout comme une classe abstraite, une interface ne peut PAS être instanciée. Ainsi, il n'est pas nécessaire de mentionner explicitement les méthodes de son "parent". Cependant, TOUTES les signatures de méthode parente font implicitement partie de l'interface d'extension ou d'implémentation de la classe abstraite. Ainsi, une fois qu'une classe appropriée (une qui peut être instanciée) étend ce qui précède, il sera nécessaire de s'assurer que chaque méthode abstraite est implémentée.
J'espère que cela aide ... et Allahu 'alam!
la source
Interface signifie une classe qui n'a pas d'implémentation de sa méthode, mais avec juste une déclaration.
D'autre part, la classe abstraite est une classe qui peut avoir une implémentation d'une méthode avec une méthode avec juste déclaration, sans implémentation.
Lorsque nous implémentons une interface dans une classe abstraite, cela signifie que la classe abstraite a hérité de toutes les méthodes de l'interface. Comme, il n'est pas important d'implémenter toute la méthode dans une classe abstraite, mais il s'agit d'une classe abstraite (par héritage aussi), donc la classe abstraite peut laisser une partie de la méthode dans l'interface sans implémentation ici. Mais, lorsque cette classe abstraite sera héritée par une classe concrète, ils doivent avoir à implémenter toutes ces méthodes non implémentées dans une classe abstraite.
la source
Compte tenu de l'interface:
Voici comment Java le voit:
Vous pouvez donc laisser certaines (ou toutes) de ces
abstract
méthodes non implémentées, comme vous le feriez dans le cas deabstract
classes étendant une autreabstract
classe.Lorsque vous
implement
uninterface
, la règle selon laquelle toutes lesinterface
méthodes doivent être implémentées dans le dérivéclass
s'applique uniquement à l'class
implémentation concrète (c'est-à-dire qui n'est pasabstract
elle-même).Si vous envisagez en effet de créer un
abstract class
hors de celui-ci, alors il n'y a pas de règle qui dit que vous avezimplement
toutes lesinterface
méthodes (notez que dans un tel cas, il est obligatoire de déclarer le dérivéclass
commeabstract
)la source
javap IAnything.class
pour générer le deuxième extrait de code.Référence: http://docs.oracle.com/javase/tutorial/java/IandI/abstract.html
la source
Les classes abstraites ne sont pas nécessaires pour implémenter les méthodes. Ainsi, même si elle implémente une interface, les méthodes abstraites de l'interface peuvent rester abstraites. Si vous essayez d'implémenter une interface dans une classe concrète (c'est-à-dire pas abstraite) et que vous n'implémentez pas les méthodes abstraites, le compilateur vous dira: Soit implémentez les méthodes abstraites, soit déclarez la classe comme abstraite.
la source