Pourquoi une classe abstraite de la mise en œuvre d'une interface peut manquer de la déclaration et la mise en œuvre de l'un de l'interface des méthodes?
Une chose curieuse qui se passe en Java lorsque vous utilisez une classe abstraite pour implémenter une interface: une partie de l'interface de méthodes peuvent être totalement absent (c'est à dire ni une déclaration abstraite ou d'une mise en œuvre effective est présent), mais le compilateur ne se plaignent pas.
Par exemple, compte tenu de l'interface:
public interface IAnything {
void m1();
void m2();
void m3();
}
la suite de la classe abstraite devient joyeusement compilé sans un avertissement ou une erreur:
public abstract class AbstractThing implements IAnything {
public void m1() {}
public void m3() {}
}
Pouvez-vous expliquer pourquoi?
- On ne peut pas créer un objet d'une classe abstraite. Donc, tant que l'application n'est pas prévue pour une classe abstraite, les objets ne peuvent pas être créés pour IAnything. Donc, c'est absolument parfait pour le compilateur. Le compilateur s'attend à ce que, tout non-abstraite de la classe qui implémente IAnything doit implémenter toutes les méthodes déclarées IAnything. Et puisque l'on doit étendre et de mettre en œuvre AbstractThing pour être en mesure de créer des objets, le compilateur génère une erreur, si cette application ne pas appliquer les méthodes de IAnything gauche par AbstractThing.
- J'ai eu une classe concrète qui a été l'extension de sa propre "AbstractThing" dans un scénario identique à présent, et même si je ne l'avais pas mis en œuvre l'une des méthodes de l'interface, il a été inexplicablement de la compilation. Maintenant, c'est de faire ce que j'attends, mais je ne peux pas comprendre ce qui était à l'origine de réussir avant. Je crois que je n'avais pas
:w
'd'un seul de ces fichiers.
Vous devez vous connecter pour publier un commentaire.
C'est parce que si une classe est abstraite, alors, par définition, vous sont nécessaires pour créer des sous-classes à instancier. Les sous-classes seront nécessaires (par le compilateur) pour implémenter toutes les méthodes d'interface que la classe abstraite à gauche.
À la suite de votre code d'exemple, essayez de faire une sous-classe de
AbstractThing
sans la mise en œuvre de lam2
méthode et de voir quelles erreurs que le compilateur vous donne. Il va vous forcer à mettre en œuvre cette méthode.Parfaitement bien.
Vous ne pouvez pas instancier les classes abstraites.. mais les classes abstraites peuvent être utilisés à la maison commune des implémentations pour les m1() et m3().
Donc si m2() de la mise en œuvre est différente pour chaque exécution, mais en m1 et m3 ne sont pas. Vous pouvez créer différents béton IAnything implémentations avec juste les différentes m2 mise en œuvre et en tirer AbstractThing -- honorer le principe DRY. La validation si l'interface est complètement mis en œuvre pour une classe abstraite est futile..
Mise à jour: 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 "abstrait public" dans la classe de base abstraite dans ce scénario.. (quelque chose de nouveau tous les jours:)
C'est très bien. Pour comprendre ce qui précède, vous devez comprendre la nature de classes abstraites en premier. Ils sont semblables à des interfaces à cet égard. C'est ce que l'Oracle dire à propos de ce ici.
De sorte que vous avez à penser à ce qui arrive quand une interface étend une autre interface. Par exemple ...
... comme vous pouvez le voir, cette compile également parfaitement bien. Tout simplement parce que, tout comme une classe abstraite, une interface ne peut PAS être instanciée. Donc, il n'est pas nécessaire de mentionner explicitement les méthodes de son "parent". Cependant, TOUS les parents signatures de méthode NE implicitement devenir une partie de l'extension de l'interface ou de la mise en œuvre de la classe abstraite. Ainsi, une fois une bonne classe (qui peut être instancié) s'étend au-dessus, il SERA nécessaire de s'assurer que chaque méthode abstraite est mis en œuvre.
Espère que ça aide... et Allahu 'alam !
Interface d'une classe qui n'a pas de mise en œuvre de la méthode, mais avec juste de la déclaration.
D'autre part, une classe abstraite est une classe qui peut avoir la mise en œuvre d'une méthode avec un peu de méthode, avec juste de la déclaration, la mise en œuvre.
Lorsque nous mettons en œuvre une interface d'une classe abstraite, sa signifie que la classe abstraite hérité de toutes les méthodes de l'interface. Comme, il n'est pas important de mettre en œuvre toutes les méthodes dans la classe abstraite mais elle revient à la classe abstraite (par héritage de trop), de sorte que la classe abstraite peut à gauche une partie de la méthode dans l'interface sans mise en œuvre ici. Mais, lorsque cette classe abstraite sera héritée par certains de la classe de béton, ils doivent avoir à implémente tous ceux appliqués méthode dans la classe abstraite.
Compte tenu de l'interface:
C'est la façon dont Java en fait le voit:
De sorte que vous pouvez laisser certaines (ou toutes) de ces
abstract
méthodes non implémentées, tout comme vous le feriez dans le cas deabstract
classes de l'extension de l'autreabstract
classe.Lorsque vous
implement
uninterface
, la règle que tous lesinterface
méthodes doivent être mises en œuvre dans le dérivéclass
, ne s'applique qu'à bétonclass
de mise en œuvre (c'est à dire, qui n'est pasabstract
lui-même).Si vous envisagez de créer une
abstract class
hors de lui, alors il n'y a aucune règle qui dit que vous avez àimplement
tous lesinterface
méthodes (à noter que dans un tel cas, il est obligatoire de déclarer la dérivéeclass
commeabstract
)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
Les classes abstraites ne sont pas tenus de mettre en œuvre les méthodes. Donc, même si elle implémente une interface, les méthodes abstraites de l'interface peut rester abstraite. Si vous essayez de mettre en œuvre une interface dans une classe concrète (c'est à dire non pas abstraite) et vous n'avez pas implémenter les méthodes abstraites le compilateur va vous dire: Soit mettre en œuvre les méthodes abstraites ou de déclarer la classe de base abstraite.