Y a-t-il une différence entre
public class A extends AbstractB implements C
{...}
contre...
public class A extends AbstractB
{...}
abstract class AbstractB implements C
{...}
Je comprends que dans les deux cas, la classe A finira par se conformer à l'interface. Dans le second cas, AbstractB
peut fournir l'implémentation des méthodes d'interface dans C
. Est-ce la seule différence?
Si je ne souhaite PAS fournir d'implémentation pour l'une des méthodes d'interface dans AbstractB
, quel style dois-je utiliser ? L'utilisation de l'un ou de l'autre a-t-elle un but caché de «documentation»?
java
interfaces
abstract-class
c_maker
la source
la source
Réponses:
Tout dépend si
AbstractB implements C
sémantiquement. C'est-à-dire si cela a un sens sémantique pourAbstractB
être implémentéC
, alors allez-y.Si nous prenons des exemples concrets, la différence sémantique devient claire.
Si A = chien, abstrait B = animal, C = IBark
Le seul choix qui a du sens est
Cela n'a aucun sens, car cela impliquerait que tous les animaux aboient.
Les autres différences entrent en jeu si vous avez plus que simplement
class A
hérité deAbstractB
. Dans # 1, ils n'ont pas besoin d'implémenter C, dans # 2, ils sont tous obligés d'implémenter C.la source
Heterotroph
il semble raisonnable de la mettre enAnimal
œuvreHeterotroph
. Si vous vous attendez à beaucoup d'autres animaux qui aboient et que vous souhaitez les traiter de la même manière, une autre classeBarkingAnimal extends Animal implements IBark
serait la voie à suivre.Heterotroph
mais merci pour votre contributionLe moyen facile de déterminer la relation d'héritage appropriée n'est pas d'examiner les classes elles-mêmes, mais le code qui appelle des méthodes sur ces classes. Quelque part dans votre code, vous avez quelque chose comme
AbstractB b = new A();
ouotherObject.addAbstractB(this);
. Dans les deux cas, vous utiliserez ultérieurement cetteAbstractB
référence pour effectuer divers appels de méthode.Dans cette situation, allez-vous vouloir appeler des méthodes de
C
? Si oui, alorsAbstractB
devrait mettre en œuvreC
. Sinon, ça ne devrait pas. Si vous n'avez pas de situations comme celle-là, vous n'avez pas besoin d'héritage et vous devez refactoriser la composition à la place, car elle est beaucoup plus lâche.la source
Ce n'est pas un objectif de documentation "caché". Il vous permet de convertir AbstractB et toutes ses sous-classes en C. Il existe en fait trois styles.
J'utiliserais celui-ci si AbstractB n'a pas implémenté logiquement C. Même s'il ne fournit pas les méthodes, il pourrait avoir un sens. Tels que Dog étend Animal met en œuvre Wag. Il n'est pas logique que tous les animaux remuent. Notez que cette approche n'empêche pas réellement AbstractB de fournir l'implémentation.
J'utiliserais celui-ci si je voulais que toutes les sous-classes implémentent l'interface ET il est logique que toutes le fassent. Tels que Beagle étend AbstractDog implémente Wag.
Celui-ci est redondant mais pourrait ajouter de la clarté.
la source