Interface avec les méthodes par défaut vs classe abstraite dans Java 8

Comme Java 8 permet une implémentation par défaut des méthodes dans l’interface appelée méthodes par défaut , il semble y avoir une confusion entre quand utiliser une abstract class .

Alors, quand devrait-on utiliser l’interface avec les méthodes par défaut et quand utiliser une classe abstraite? Les classes abstraites sont-elles encore utiles dans ce scénario?

Il y a beaucoup plus de classes abstraites que d’implémentations de méthodes par défaut (telles que l’état privé), mais à partir de Java 8, chaque fois que vous avez le choix, vous devriez utiliser la méthode defender (aka default ) dans l’interface.

La contrainte sur la méthode par défaut est qu’elle ne peut être implémentée que dans les termes d’appels à d’autres méthodes d’interface, sans référence à un état d’implémentation particulier. Le principal cas d’utilisation est donc les méthodes de niveau supérieur et de commodité.

La bonne chose à propos de cette nouvelle fonctionnalité est que, avant d’être obligé d’utiliser une classe abstraite pour les méthodes pratiques, contraignant ainsi l’implémenteur à un inheritance unique, vous pouvez désormais avoir un design vraiment propre avec juste une interface et un minimum d’implémentation. effort forcé sur le programmeur.

Il y a quelques différences techniques. Les classes abstraites peuvent encore faire plus par rapport aux interfaces Java 8:

  1. La classe abstraite peut avoir un constructeur.
  2. Les classes abstraites sont plus structurées et peuvent contenir un état.

Conceptuellement, le but principal des méthodes de défense est une compatibilité en amont après l’introduction de nouvelles fonctionnalités (en tant que fonctions lambda) dans Java 8.

Ceci est décrit dans cet article . Pensez à forEach collection.

 List< ?> list = … list.forEach(…); 

Le forEach n’est pas déclaré par java.util.List ni l’interface java.util.Collection moment. Une solution évidente consisterait simplement à append la nouvelle méthode à l’interface existante et à fournir l’implémentation requirejse dans le JDK. Cependant, une fois publié, il est impossible d’append des méthodes à une interface sans casser l’implémentation existante.

L’avantage apporté par les méthodes par défaut est qu’il est maintenant possible d’append une nouvelle méthode par défaut à l’interface et qu’elle ne rompt pas les implémentations.

Ces deux sont très différents:

Les méthodes par défaut consistent à append des fonctionnalités externes aux classes existantes sans modifier leur état.

Et les classes abstraites sont un type d’inheritance normal, ce sont des classes normales qui sont destinées à être étendues.

Chaque fois que nous avons le choix entre une classe abstraite et une interface, nous devrions toujours (presque) préférer les méthodes par défaut (également appelées défenseurs ou extensions virtuelles).

  1. Les méthodes par défaut ont mis fin aux modèles classiques d’interface et à une classe compagnon qui implémente la plupart ou toutes les méthodes de cette interface. Un exemple est Collection and AbstractCollection . Maintenant, nous devrions implémenter les méthodes dans l’interface elle-même pour fournir des fonctionnalités par défaut. Les classes qui implémentent l’interface ont le choix de remplacer les méthodes ou hériter de l’implémentation par défaut.
  2. Une autre utilisation importante des méthodes par défaut est l’ interface evolution . Supposons que j’ai eu une classe Ball comme:

    public class Ball implements Collection { ... }

Maintenant, dans Java 8, un nouveau stream de fonctionnalités est introduit. Nous pouvons obtenir un stream en utilisant la méthode de stream ajoutée à l’interface. Si stream n’était pas une méthode par défaut, toutes les implémentations de l’interface Collection se seraient cassées car elles n’implémenteraient pas cette nouvelle méthode. L’ajout d’une méthode autre que la méthode par défaut à une interface n’est pas source-compatible .

Mais supposons que nous ne recompilions pas la classe et n’utilisions pas un ancien fichier jar contenant cette classe Ball . La classe se chargera bien sans cette méthode manquante, des instances peuvent être créées et tout semble fonctionner correctement. MAIS si le programme invoque la méthode du stream sur l’instance de Ball nous obtiendrons AbstractMethodError . Donc, rendre la méthode par défaut a résolu les deux problèmes.

Concernant votre requête de

Alors, quand devrait-on utiliser l’interface avec les méthodes par défaut et quand utiliser une classe abstraite? Les classes abstraites sont-elles encore utiles dans ce scénario?

La documentation Java fournit une réponse parfaite.

Classes abstraites comparées aux interfaces:

Les classes abstraites sont similaires aux interfaces. Vous ne pouvez pas les instancier et ils peuvent contenir un mélange de méthodes déclarées avec ou sans implémentation.

Cependant, avec les classes abstraites, vous pouvez déclarer des champs qui ne sont ni statiques ni finaux et définir des méthodes concrètes publiques, protégées et privées.

Avec les interfaces, tous les champs sont automatiquement publics, statiques et finaux, et toutes les méthodes que vous déclarez ou définissez (comme méthodes par défaut) sont publiques. De plus, vous ne pouvez étendre qu’une seule classe, qu’elle soit abstraite ou non, alors que vous pouvez implémenter un nombre quelconque d’interfaces.

Des cas d’utilisation pour chacun d’entre eux ont été expliqués dans le message ci-dessous:

Quelle est la différence entre une interface et une classe abstraite?

Les classes abstraites sont-elles encore utiles dans ce scénario?

Oui. Ils sont encore utiles. Ils peuvent contenir des méthodes et des atsortingbuts non statiques et non définitifs ( protégés, privés et publics ), ce qui n’est pas possible même avec les interfaces Java-8.

Comme décrit dans cet article,

Classes abstraites versus interfaces dans Java 8

Après avoir introduit la méthode par défaut, il semble que les interfaces et les classes abstraites soient identiques. Cependant, leur concept est encore différent en Java 8.

La classe abstraite peut définir un constructeur. Ils sont plus structurés et peuvent être associés à un état. En revanche, la méthode par défaut peut être implémentée uniquement en termes d’invocation d’autres méthodes d’interface, sans référence à un état d’implémentation particulier. Par conséquent, l’utilisation à des fins différentes et le choix entre deux dépend vraiment du contexte du scénario.

Les méthodes par défaut dans l’interface Java permettent l’ évolution de l’interface .

Étant donné une interface existante, si vous souhaitez y append une méthode sans rompre la compatibilité binary avec les anciennes versions de l’interface, vous avez deux options en mains: append une méthode par défaut ou une méthode statique. En effet, toute méthode abstraite ajoutée à l’interface devrait être implémentée par les classes ou les interfaces implémentant cette interface.

Une méthode statique est unique pour une classe. Une méthode par défaut est unique pour une instance de la classe.

Si vous ajoutez une méthode par défaut à une interface existante, les classes et les interfaces qui implémentent cette interface n’ont pas besoin de l’implémenter. Ils peuvent

  • implémenter la méthode par défaut et remplace l’implémentation dans l’interface implémentée.
  • re-déclarer la méthode (sans implémentation) qui la rend abstraite.
  • ne rien faire (alors la méthode par défaut de l’interface implémentée est simplement héritée).

Plus sur le sujet ici .

Pourquoi nous devons utiliser la classe abstraite:

  1. La classe abstraite peut avoir des méthodes abstraites et non abstraites.
  2. La classe abstraite ne prend pas en charge l’inheritance multiple.
  3. La classe abstraite peut avoir des variables finales, non finales, statiques et non statiques.
  4. La classe abstraite peut avoir des méthodes statiques, une méthode principale et un constructeur.
  5. La classe abstraite peut fournir l’implémentation de l’interface.
  6. Le mot-clé abstract est utilisé pour déclarer une classe abstraite.

Pourquoi nous devons utiliser l’interface:

  1. L’interface est le niveau le plus abstrait de la conception de votre application
  2. L’interface prend en charge l’inheritance multiple.
  3. Interface créée uniquement pour décrire les signatures des sous-classes
  4. L’interface n’a que des variables statiques et finales.
  5. Utilisez la méthode par défaut uniquement pour étendre certaines interfaces, par exemple, lib externe. Mais surtout ce n’est pas une bonne pratique 🙂

La règle Remi Forax est Vous ne concevez pas avec des classes abstraites. Vous concevez votre application avec des interfaces . Watever est la version de Java, quel que soit le langage. Il est soutenu par le principe de ségrégation des interfaces dans les principes SOL I D.

Vous pouvez ensuite utiliser des classes abstraites pour factoriser le code. Maintenant, avec Java 8, vous pouvez le faire directement dans l’interface. Ceci est une facilité, pas plus.

quand utiliser l’interface avec les méthodes par défaut et quand utiliser une classe abstraite?

Compatibilité descendante: Imaginez que votre interface soit implémentée par des centaines de classes, la modification de cette interface obligera tous les utilisateurs à implémenter la méthode nouvellement ajoutée, même si cela peut ne pas être essentiel pour de nombreuses autres classes qui implémentent votre interface. être une interface fonctionnelle

Faits et ressortingctions:

1-Peut uniquement être déclaré dans une interface et non dans une classe ou une classe abstraite.

2-Doit fournir un corps

3-Il n’est pas supposé être abstrait comme les autres méthodes normales utilisées dans une interface.

Les méthodes par défaut de l’interface Java doivent être utilisées davantage pour fournir une implémentation factice d’une fonction, évitant ainsi à toute classe d’implémentation de cette interface de déclarer toutes les méthodes abstraites, même si elles ne veulent en gérer qu’une. Les méthodes par défaut dans l’interface remplacent ainsi en quelque sorte le concept de classe d’adaptateur.

Les méthodes de la classe abstraite sont cependant supposées donner une implémentation significative que toute classe enfant ne devrait remplacer que si nécessaire pour remplacer une fonctionnalité commune.

@ narendra-pathai: S’il vous plaît pensez d’abord du principe ouvert / fermé. Les méthodes par défaut des interfaces le VIOLENT. C’est une mauvaise fonctionnalité en Java. Cela encourage une mauvaise conception, une mauvaise architecture, une faible qualité de logiciel. Je suggère de ne pas utiliser complètement les méthodes par défaut.

Posez-vous quelques questions: – Pourquoi ne pouvez-vous pas mettre vos méthodes dans la classe abstraite? Auriez-vous besoin de plus d’un cours abstrait? Pensez ensuite à la responsabilité de votre classe. Êtes-vous sûr que toutes les méthodes que vous allez mettre dans la même classe remplissent vraiment le même objective? Peut-être vous distinguerez plusieurs objectives et diviserez ensuite votre classe en plusieurs classes, pour chaque objective sa propre classe.