web-dev-qa-db-fra.com

Quelle est la vraie signification (utilisation) du polymorphisme

Je suis nouveau à la POO. Bien que je comprenne ce qu'est le polymorphisme, mais je ne parviens pas à en obtenir le véritable usage. Je peux avoir des fonctions avec un nom différent. Pourquoi devrais-je essayer d'implémenter le polymorphisme dans mon application.

25
sultandeep

Réponse classique: Imaginez une classe de base Shape. Il expose une méthode GetArea. Imaginez une classe Square et une classe Rectangle et une classe Circle. Au lieu de créer des méthodes GetSquareArea, GetRectangleArea et GetCircleArea distinctes, vous devez implémenter une seule méthode dans chacune des classes dérivées. Vous n'avez pas besoin de savoir quelle sous-classe exacte de Shape vous utilisez, vous appelez simplement GetArea et vous obtenez votre résultat, quel que soit le type concret correspondant.

Regardez ce code:

#include <iostream>
using namespace std;

class Shape
{
public:
  virtual float GetArea() = 0;
};

class Rectangle : public Shape
{
public:
  Rectangle(float a) { this->a = a; }
  float GetArea() { return a * a; }
private:
  float a;
};

class Circle : public Shape
{
public:
  Circle(float r) { this->r = r; }
  float GetArea() { return 3.14f * r * r; }
private:
  float r;
};

int main()
{
  Shape *a = new Circle(1.0f);
  Shape *b = new Rectangle(1.0f);

  cout << a->GetArea() << endl;
  cout << b->GetArea() << endl;
}

Une chose importante à noter ici est que vous n'avez pas besoin de connaître le type exact de la classe que vous utilisez, mais seulement le type de base, et vous obtiendrez le bon résultat. Ceci est également très utile dans des systèmes plus complexes.

Amusez-vous à apprendre!

21
Marcin Seredynski

Avez-vous déjà ajouté deux entiers avec +, puis avez-vous ajouté un entier à un nombre à virgule flottante avec +?

Avez-vous déjà connecté x.toString() pour vous aider à déboguer quelque chose?

Je pense que vous appréciez probablement déjà le polymorphisme, juste sans connaître le nom.

16
Ken

Dans un langage strictement typé, le polymorphisme est important pour avoir une liste/collection/tableau d'objets de types différents. En effet, les listes/tableaux sont eux-mêmes typés pour ne contenir que des objets du type correct.

Imaginons par exemple que nous ayons:

// the following is pseudocode M'kay:
class Apple;
class banana;
class kitchenKnife;

Apple foo;
banana bar;
kitchenKnife bat;

Apple *shoppingList = [foo, bar, bat]; // this is illegal because bar and bat is
                                       // not of type Apple.

Pour résoudre ceci:

class groceries;
class Apple inherits groceries;
class banana inherits groceries;
class kitchenKnife inherits groceries;

Apple foo;
banana bar;
kitchenKnife bat;

groceries *shoppingList = [foo, bar, bat]; // this is OK

En outre, le traitement de la liste des éléments est plus simple. Disons par exemple que toutes les courses implémentent la méthode price(), le traitement est simple:

int total = 0;
foreach (item in shoppingList) {
    total += item.price();
}

Ces deux caractéristiques sont au cœur de ce que fait le polymorphisme.

7
slebetman

Le polymorphisme est le fondement de la programmation orientée objet. Cela signifie qu'un objet peut être un autre projet. Alors, comment un objet peut-il devenir autre, cela est possible en suivant

  1. Héritage
  2. Remplacement/implémentation du comportement de la classe parent
  3. Liaison d'objet d'exécution

L'un des principaux avantages est la mise en œuvre de commutateurs. Disons que vous codez une application qui doit parler à une base de données. Et vous définissez une classe qui effectue cette opération de base de données pour vous et qui est censée effectuer certaines opérations telles que Ajouter, Supprimer, Modifier. Vous savez que la base de données peut être implémentée de plusieurs manières, il peut s'agir de parler à un système de fichiers ou à un serveur RDBM tel que MySQL, etc. Ainsi, en tant que programmeur, définissez une interface que vous pourriez utiliser, telle que ...

public interface DBOperation {
    public void addEmployee(Employee newEmployee);
    public void modifyEmployee(int id, Employee newInfo);
    public void deleteEmployee(int id);
}

Maintenant, vous pouvez avoir plusieurs implémentations, disons que nous en avons une pour le SGBDR et une autre pour le système de fichiers direct.

public class DBOperation_RDBMS implements DBOperation
    // implements DBOperation above stating that you intend to implement all
    // methods in DBOperation
    public void addEmployee(Employee newEmployee) {
          // here I would get JDBC (Java's Interface to RDBMS) handle
          // add an entry into database table.
    }
    public void modifyEmployee(int id, Employee newInfo) {
          // here I use JDBC handle to modify employee, and id to index to employee
    }
    public void deleteEmployee(int id) {
          // here I would use JDBC handle to delete an entry
    }
}

Permet la mise en oeuvre de la base de données du système de fichiers

public class DBOperation_FileSystem implements DBOperation
    public void addEmployee(Employee newEmployee) {
          // here I would Create a file and add a Employee record in to it
    }
    public void modifyEmployee(int id, Employee newInfo) {
          // here I would open file, search for record and change values
    }
    public void deleteEmployee(int id) {
          // here I search entry by id, and delete the record
    }
}

Permet de voir comment principal peut basculer entre les deux

public class Main {
    public static void main(String[] args) throws Exception {
          Employee emp = new Employee();
          ... set employee information

          DBOperation dboper = null;
          // declare your db operation object, not there is no instance
          // associated with it

          if(args[0].equals("use_rdbms")) {
               dboper = new DBOperation_RDBMS();
               // here conditionally, i.e when first argument to program is
               // use_rdbms, we instantiate RDBM implementation and associate
               // with variable dboper, which delcared as DBOperation.
               // this is where runtime binding of polymorphism kicks in
               // JVM is allowing this assignment because DBOperation_RDBMS
               // has a "is a" relationship with DBOperation.
          } else if(args[0].equals("use_fs")) {
               dboper = new DBOperation_FileSystem(); 
               // similarly here conditionally we assign a different instance.
          } else {
               throw new RuntimeException("Dont know which implemnation to use");
          }

          dboper.addEmployee(emp);
          // now dboper is refering to one of the implementation 
          // based on the if conditions above
          // by this point JVM knows dboper variable is associated with 
          // 'a' implemenation, and it will call appropriate method              
    }
}

Vous pouvez utiliser le concept de polymorphisme dans de nombreux endroits, par exemple: vous écrivez un décodeur d’images, et vous devez prendre en charge l’ensemble des images telles que jpg, tif, png, etc. Ainsi, votre application définira une interface et fonctionnera sur elle directement. Et vous auriez une liaison d'exécution de diverses implémentations pour chacun des formats jpg, tif, pgn, etc.

Une autre utilisation importante est que, si vous utilisez Java, la plupart du temps, vous utiliseriez l'interface List afin de pouvoir utiliser ArrayList aujourd'hui ou une autre interface à mesure que votre application grandit ou que ses besoins changent. 

5
chinmaya

L'avantage du polymorphisme est que le code client n'a pas besoin de s'inquiéter de l'implémentation réelle d'une méthode . Regardez l'exemple suivant . Ici, CarBuilder ne sait rien sur ProduceCar (). liste des voitures (CarsToProduceList), il produira toutes les voitures nécessaires en conséquence.

class CarBase
{
    public virtual void ProduceCar()
    {
        Console.WriteLine("don't know how to produce");
    }
}

class CarToyota : CarBase
{
    public override void ProduceCar()
    {
        Console.WriteLine("Producing Toyota Car ");
    }
}

class CarBmw : CarBase
{
    public override void ProduceCar()
    {
        Console.WriteLine("Producing Bmw Car");
    }
}

class CarUnknown : CarBase { }

class CarBuilder
{
    public List<CarBase> CarsToProduceList { get; set; }

    public void ProduceCars()
    {
        if (null != CarsToProduceList)
        {
            foreach (CarBase car in CarsToProduceList)
            {
                car.ProduceCar();// doesn't know how to produce
            }
        }

    }
}

class Program
{
    static void Main(string[] args)
    {
        CarBuilder carbuilder = new CarBuilder();
        carbuilder.CarsToProduceList = new List<CarBase>() { new CarBmw(), new CarToyota(), new CarUnknown() };            
        carbuilder.ProduceCars();
    }
}
5
LittleBit

Un des avantages les plus importants des opérations polymorphes est sa capacité à s’étendre ..___. Vous pouvez utiliser les mêmes opérations sans modifier les interfaces et les implémentations existantes uniquement parce que vous aviez besoin de nouveaux éléments.

Tout ce que nous voulons du polymorphisme - c’est simplifier notre décision de conception et rendre notre conception plus extensible et élégante . Vous devriez également attirer l’attention sur le principe ouvert-fermé ( http://en.wikipedia.org/wiki/Open/closed_principle ) et pour SOLID ( http://en.wikipedia.org/wiki/Solid_%28Object_Oriented_Design%29 ) pouvant vous aider à comprendre les principes clés OO.

P.S. Je pense que vous parlez de "polymorphisme dynamique" ( http://en.wikipedia.org/wiki/polymorphisme_dynamique ), car il existe une telle chose comme "polymorphisme statique" ( http: //en.wikipedia .org/wiki/Template_metaprogramming # Static_polymorphism ).

1
Sergey Teplyakov

Le polymorphisme vous permet d'écrire du code utilisant des objets. Vous pouvez ensuite créer ultérieurement de nouvelles classes que votre code existant peut utiliser sans aucune modification.

Par exemple, supposons que vous ayez une fonction Lib2Groc(vehicle) qui dirige un véhicule de la bibliothèque à l’épicerie. Il doit indiquer aux véhicules de tourner à gauche pour pouvoir appeler TurnLeft() sur l'objet véhicule, entre autres. Ensuite, si quelqu'un invente plus tard un nouveau véhicule, comme un aéroglisseur, il peut être utilisé par Lib2Groc sans modification.

1
recursive

Vous n'avez pas besoin de polymorphisme.

En attendant.

Ensuite, son friggen génial.

Une réponse simple à laquelle vous aurez souvent affaire:

Quelqu'un doit passer en revue une collection de choses. Disons qu'ils demandent une collection de type MySpecializedCollectionOfAwesome. Mais vous avez eu affaire à vos instances de Awesome as List. Alors, maintenant, vous allez devoir créer une instance de MSCOA et la remplir avec chaque instance de Awesome que vous avez dans votre liste <T>. Grande douleur dans les fesses, non?

Eh bien, s’ils demandent un IEnumerable <Awesome>, vous pouvez leur remettre l’une des nombreuses collections d’Awesome. Vous pouvez leur remettre un tableau (Awesome []) ou une liste (List <Awesome>) ou une collection observable d’Awesome ou TOUT AUTRE que vous gardiez votre Awesome dans lequel implémente IEnumerable <T>. 

La puissance du polymorphisme vous permet de sécuriser le type, tout en étant suffisamment flexible pour que vous puissiez utiliser une instance de nombreuses façons différentes sans créer de tonnes de code qui traite spécifiquement ce type ou ce type.

0
Will

J'imagine que parfois les objets sont appelés dynamiquement. Vous n'êtes pas sûr que l'objet soit un triangle, un carré, etc., dans une forme classique poly. Exemple. 

Donc, pour laisser toutes ces choses derrière nous, appelons simplement la fonction de classe dérivée et supposons que celle de la classe dynamique sera appelée. 

Vous ne voudriez pas que ce soit un carré, un triangle ou un rectangle. Vous vous souciez juste de la région. Par conséquent, la méthode getArea sera appelée en fonction de l'objet dynamique transmis. 

0
Kapil D

Applications à onglets

Une bonne application pour moi est les boutons génériques (pour tous les onglets) dans une application à onglets - même le navigateur que nous utilisons est en train de mettre en œuvre Polymorphism car il ne connaît pas l'onglet que nous utilisons lors de la compilation ( dans le code autrement dit). Il est toujours déterminé au moment de l'exécution (maintenant! Lorsque nous utilisons le navigateur.)

0
Failed Scientist