web-dev-qa-db-fra.com

Polymorphisme vs héritage

Supposons que j'ai deux classes: Animal et Dog. Dog est une sous-classe de Animal. Je fais le code suivant:

Animal a = new Dog();

Maintenant, je peux appeler des méthodes de la classe Dog via la variable a. 

Mais ma question est la suivante: si je peux appeler toutes les méthodes d’Animal à travers les objets Dog (héritage), pourquoi utiliser le principe du polymorphisme? Je peux simplement déclarer:

Dog d = new Dog();

Avec cette déclaration, vous pouvez utiliser toutes les méthodes d’Animal et de chien. Alors, pourquoi utiliser le polymorphisme? Merci beaucoup pour votre réponse.

18
Assaf

En Java, les concepts de polymorphisme et d'héritage sont "soudés"; en général, il ne doit pas en être ainsi:

  • Le polymorphisme vous permet d'appeler les méthodes d'une classe sans connaître le type exact de la classe
  • L'héritage permet aux classes dérivées de partager les interfaces et le code de leurs classes de base

Il y a des langues où l'héritage est découplé du polymorphisme:

  • En C++, vous pouvez hériter d'une classe sans générer de comportement polymorphe (c'est-à-dire ne marquez pas les fonctions de la classe de base avec virtual)
  • En Objective C, vous pouvez implémenter une méthode sur une classe non liée et l'appeler depuis un emplacement ne connaissant que la signature de la méthode.

Pour revenir à Java, la raison d'utiliser le polymorphisme est de découpler votre code des détails de la mise en œuvre de ses contreparties: par exemple, si vous pouvez écrire une méthode Feed(Animal animal) qui fonctionne pour toutes sortes d'animaux, la méthode restera applicable lorsque vous ajoutez plus de sous-classes ou d’implémentations de Animal. Ceci contraste avec la méthode Feed(Dog dog) qui serait étroitement liée aux chiens.

Jusqu'au

Dog d = new Dog();

selon la déclaration, il n'y a pas de raison générale de l'éviter si vous savez que le reste de votre méthode traite spécifiquement des chiens. Cependant, dans de nombreux cas, ce n'est pas le cas par la suite: par exemple, votre classe ou vos méthodes seraient souvent insensibles à l'implémentation exacte, par exemple

List<Integer> numbers = new ArrayList<Integer>();

Dans de tels cas, vous pouvez remplacer new ArrayList<Integer>() par new LinkedList<Integer>() et know que votre code va compiler. En revanche, si votre liste numbers avait été déclarée en tant que ArrayList<Integer> numbers, un tel basculement n'aurait peut-être pas été une certitude.

Cela s'appelle "programmation sur une interface". Il y a un très bon réponse sur Stack Overflow qui l'explique.

23
dasblinkenlight

Vous pouvez avoir d'autres implémentations de la classe Animal, telles que Cat. Alors tu peux dire

Animal a = new Dog();
Animal b = new Cat();

Vous pouvez appeler des méthodes de la classe Animal sans vous soucier de son implémentation réelle et polymorphism appellera la bonne méthode. Par exemple.

a.speak();  // "Woof"

b.speak();  // "Meow"

En réalité, ce n'est pas "Polymorphisme vs Héritage" mais "Polymorphisme utilisant l'Héritage".

4
rgettman

Le polymorphisme vous permet d’écrire une méthode qui fonctionne pour tout Animal:

public void pet(Animal animal) {
   ...
}

Cette méthode accepterait Dog, Cat, etc., y compris les sous-classes de Animal qui n'ont pas encore été écrites.

Si la méthode prenait Dog, elle ne fonctionnerait pas pour Cat etc.

4
NPE

Si vous êtes certain que ce sera toujours un chien, il n'y a aucune raison de le faire. Vous pouvez également utiliser Dog d = new Dog (); comme vous l'avez décrit. Mais disons que vous avez utilisé une méthode au lieu d'un constructeur. La méthode renvoyait un animal et vous ne sauriez pas quelle implémentation d’animal vous obtiendriez. Vous pourrez toujours utiliser les mêmes méthodes sur l'animal (même s'il s'agit d'un chien, d'un chat d'éléphant, etc.).

Pour des raisons d'extensibilité, l'héritage simplifie les choses. Lorsque vous voulez créer un éléphant ou un chat qui partage également certaines méthodes animales, vous pouvez facilement les obtenir en prenant animal comme classe supérieure.

1
Peter Rasmussen

Normalement, la question que vous avez posée est plus similaire à Inheritance vs Composition :). Un exemple plus concret de pourquoi il est bon d’utiliser le polymorphisme est, par exemple, l’utilisation du modèle de conception de stratégie. Vous pouvez avoir plusieurs implémentations de TaxPolicy: UsaTaxPolicy, CanadaTaxPolicy, EuTaxPolicy, etc. Si vous avez la méthode CalculateFinalPrice, qui doit également calculer la taxe, vous injectez la bonne implémentation et un bon calcul est exécuté, peu importe si vous avez passé Usa, Canada ou Mise en œuvre de l'UE.

0
Jakub Kubrynski

l'héritage est le polymorphisme dynamique. Je veux dire lorsque vous supprimez l'héritage, vous ne pouvez plus remplacer.