web-dev-qa-db-fra.com

Qu'est-ce que le polymorphisme en Javascript?

J'ai lu un article que j'ai trouvé sur Internet sur polymorphisme. Mais je pense que je ne pouvais pas tout à fait comprendre son sens et son importance. La plupart des articles ne disent pas pourquoi c'est important et comment je peux obtenir un comportement polymorphe dans OOP (bien sûr en JavaScript).

Je ne peux fournir aucun exemple de code car je ne sais pas comment le mettre en œuvre. Mes questions sont donc les suivantes:

  1. Qu'Est-ce que c'est?
  2. Pourquoi on en a besoin?
  3. Comment ça fonctionne?
  4. Comment puis-je obtenir ce comportement polymorphe en javascript?

J'ai cet exemple. Mais on comprend aisément quel sera l’issue de ce code. Cela ne donne aucune idée précise du polymorphisme lui-même.

function Person(age, weight) {
    this.age = age;
    this.weight = weight;
    this.getInfo = function() {
        return "I am " + this.age + " years old " +
        "and weighs " + this.weight +" kilo.";
    }
}
function Employee(age, weight, salary) {
    this.salary = salary;
    this.age = age;
    this.weight = weight;
    this.getInfo = function() {
        return "I am " + this.age + " years old " +
        "and weighs " + this.weight +" kilo " +
        "and earns " + this.salary + " dollar.";
    }
}

Employee.prototype = new Person();
Employee.prototype.constructor = Employee;
  // The argument, 'obj', can be of any kind
  // which method, getInfo(), to be executed depend on the object
  // that 'obj' refer to.

function showInfo(obj) {
    document.write(obj.getInfo() + "<br>");
}

var person = new Person(50,90);
var employee = new Employee(43,80,50000);
showInfo(person);
showInfo(employee);
80
AL-zami

Le polymorphisme est l’un des principes de la programmation orientée objet (OOP). C'est la pratique de concevoir des objets pour partager des comportements et pour pouvoir remplacer des comportements partagés par des comportements spécifiques. Le polymorphisme profite de l'héritage pour y arriver.

Dans OOP tout est considéré comme modélisé comme un objet. Cette abstraction peut être assimilée à une base de données pour une voiture ou aussi large qu'un simple type de voiture avec une année, une marque et un modèle.

Pour avoir un scénario de voiture polymorphe, il faudrait le type de voiture de base, puis les sous-classes qui hériteraient d'une voiture et fourniraient leurs propres comportements en plus des comportements de base d'une voiture. Par exemple, une sous-classe pourrait être TowTruck, qui aurait toujours une marque et un modèle d'année, mais pourrait également avoir des comportements et propriétés supplémentaires qui pourraient être aussi fondamentaux qu'un indicateur pour IsTowing, aussi compliqués que les détails de l'ascenseur.

Pour revenir à l'exemple des personnes et des employés, tous les employés sont des personnes, mais tous ne sont pas des employés. Ce qui veut dire que les gens seront la super classe et les employés la sous-classe. Les gens peuvent avoir des âges et des poids, mais ils n'ont pas de salaire. Les employés sont des personnes, ils ont donc intrinsèquement un âge et un poids, mais aussi parce qu'ils sont des employés, ils auront un salaire.

Donc, pour faciliter ceci, nous allons d’abord écrire la super classe (Personne)

function Person(age,weight){
 this.age = age;
 this.weight = weight;
}

Et nous donnerons à la personne la possibilité de partager ses informations

Person.prototype.getInfo = function(){
 return "I am " + this.age + " years old " +
    "and weighs " + this.weight +" kilo.";
};

Ensuite, nous souhaitons avoir une sous-classe de personne, employé

function Employee(age,weight,salary){
 this.age = age;
 this.weight = weight;
 this.salary = salary;
}
Employee.prototype = new Person();

Et nous remplacerons le comportement de getInfo en définissant un comportement plus approprié à un employé.

Employee.prototype.getInfo = function(){
 return "I am " + this.age + " years old " +
    "and weighs " + this.weight +" kilo " +
    "and earns " + this.salary + " dollar.";  
};

Ceux-ci peuvent être utilisés de la même manière que votre code d'origine

var person = new Person(50,90);
var employee = new Employee(43,80,50000);

console.log(person.getInfo());
console.log(employee.getInfo());

Cependant, il n'y a pas grand chose à gagner avec l'utilisation de l'héritage ici car le constructeur de Employee est si similaire à celui de personne, et la seule fonction du prototype est remplacée. Le pouvoir de la conception polymorphe est de partager des comportements.

90
Travis J

Comme expliqué dans cette autre réponse , le polymorphisme a différentes interprétations.

La meilleure explication sur le sujet que j'ai jamais lue est un article de Luca Cardelli , un théoricien des types renommé. L'article est nommé Comprendre les types, l'abstraction de données et le polymorphisme .

Qu'Est-ce que c'est?

Cardelli définit plusieurs types de polymorphisme dans cet article:

  • Universel
    • paramétrique
    • inclusion
  • Ad hoc
    • surcharge
    • coercition

Peut-être qu'en JavaScript, il est un peu plus difficile de voir les effets du polymorphisme car les types de polymorphisme plus classiques sont plus évidents dans les systèmes de types statiques, alors que JavaScript possède un système de types dynamique.

Ainsi, par exemple, il n'y a pas de surcharge de méthodes ou de fonctions, ni de contraintes de type automatiques lors de la compilation en JavaScript. Dans un langage dynamique, nous prenons la plupart de ces choses pour acquises. Nous n'avons pas non plus besoin de quelque chose comme un polymorphisme paramétrique en JavaScript en raison de la nature dynamique du langage.

Néanmoins, JavaScript a une forme d'héritage de type qui émule les mêmes idées de polymorphisme de sous-type (classées comme polymorphisme d'inclusion par Cardelli ci-dessus) d'une manière similaire à celle que nous utilisons habituellement dans d'autres langages de programmation orientés objet comme Java ou C # (comme expliqué dans une autre réponse que j'ai partagée ci-dessus).

Une autre forme de polymorphisme très typique dans les langages dynamiques est appelée typage de canard .

C'est une erreur de croire que le polymorphisme n'est lié qu'à la programmation orientée objet. D'autres modèles de programmation (fonctionnels, procéduraux, logiques, etc.) offrent différentes formes de polymorphisme dans leurs systèmes de types, probablement d'une manière peu familière à ceux qui ne sont utilisés que pour la programmation orientée objet.

Pourquoi en avons-nous besoin?

Le polymorphisme favorise de nombreux bons attributs dans les logiciels, entre autres, il favorise la modularité et la réutilisabilité et rend le système de types plus flexible et malléable. Sans cela, il serait très difficile de raisonner sur les types. Le polymorphisme garantit qu'un type peut être remplacé par d'autres compatibles à condition de satisfaire une interface publique, ce qui favorise également le masquage d'informations et la modularité.

Comment ça marche?

Ce n’est pas simple de répondre, différentes langues ont différentes façons de l’appliquer. Dans le cas de JavaScript, comme mentionné ci-dessus, vous le verrez se matérialiser sous forme de hiérarchies de types à l'aide de héritage prototypal et vous pouvez également l'exploiter à l'aide de la frappe à la machine.

Le sujet est un peu large et vous avez ouvert deux nombreuses questions dans un seul post. Il est peut-être préférable de commencer par lire le document de Cardelli, puis d'essayer de comprendre le polymorphisme indépendamment de tout langage ou paradigme de programmation, puis de commencer à faire des associations entre les concepts théoriques et ce qu'un langage particulier, tel que JavaScript, peut offrir pour mettre en œuvre ces idées.

23
Edwin Dalorzo

Quel est le but du polymorphisme?

Le polymorphisme rend un système de types statiques plus flexible sans perte de sécurité (significative) en types statiques en assouplissant les conditions d'équivalence de types. La preuve reste qu'un programme ne fonctionnera que s'il ne contient aucune erreur de type.

Une fonction polymorphe ou un type de données est plus général qu'un monomorphe, car il peut être utilisé dans un plus grand nombre de scénarios. En ce sens, le polymorphisme représente l'idée de généralisation dans des langages strictement typés.

Comment cela s'applique-t-il à Javascript?

Javascript a un système de types faible et dynamique. Un tel système de types est équivalent à un système de types strict contenant un seul type. Nous pouvons considérer ce type comme un type d'union énorme (pseudo syntaxe):

type T =
 | Undefined
 | Null
 | Number
 | String
 | Boolean
 | Symbol
 | Object
 | Array
 | Map
 | ...

Chaque valeur sera associée à l'une de ces alternatives de type au moment de l'exécution. Et comme Javascript est faiblement typé, chaque valeur peut changer de type autant de fois que nécessaire.

Si nous prenons une perspective théorique de type et considérons qu’il n’ya qu’un seul type, nous pouvons dire avec certitude que le système de types de Javascript n’a pas de notion de polymorphisme. Au lieu de cela, nous avons le typage de canard et la coercition de type implicite.

Mais cela ne devrait pas nous empêcher de penser aux types dans nos programmes. En raison du manque de types en Javascript, nous devons les déduire pendant le processus de codage. Notre esprit doit remplacer le compilateur manquant, c'est-à-dire que dès que nous examinons un programme, nous devons reconnaître non seulement les algorithmes, mais également les types sous-jacents (peut-être polymorphes). Ces types nous aideront à construire des programmes plus fiables et plus robustes.

Afin de le faire correctement, je vais vous donner un aperçu des manifestations les plus courantes du polymorphisme.

Polymorphisme paramétrique (aka génériques)

Le polymorphisme paramétrique dit que les différents types sont interchangeables car les types n'ont aucune importance. Une fonction qui définit un ou plusieurs paramètres de type polymorphe paramétrique ne doit rien savoir des arguments correspondants, mais les traiter de la même manière, car ils peuvent adopter n'importe quel type. C'est assez restrictif, car une telle fonction ne peut fonctionner qu'avec les propriétés de ses arguments qui ne font pas partie de leurs données:

// parametric polymorphic functions

const id = x => x;

id(1); // 1
id("foo"); // "foo"

const k = x => y => x;
const k_ = x => y => y;

k(1) ("foo"); // 1
k_(1) ("foo"); // "foo"

const append = x => xs => xs.concat([x]);

append(3) ([1, 2]); // [1, 2, 3]
append("c") (["a", "b"]); // ["a", "b", "c"]

Polymorphisme ad hoc (alias surcharge)

Le polymorphisme ad hoc indique que différents types sont équivalents pour un but spécifique uniquement. Pour être équivalent en ce sens, un type doit implémenter un ensemble de fonctions spécifiques à cette fin. Une fonction qui définit un ou plusieurs paramètres de type polymorphe ad hoc doit ensuite savoir quels ensembles de fonctions sont associés à chacun de ses arguments.

Le polymorphisme ad hoc rend une fonction compatible avec un plus grand domaine de types. L'exemple suivant illustre l'objectif "mappage" et explique comment les types peuvent implémenter cette contrainte. Au lieu d'un ensemble de fonctions, la contrainte "mappable" n'inclut qu'une seule fonction map:

// Option type
class Option {
  cata(pattern, option) {
    return pattern[option.constructor.name](option.x);
  }
  
  map(f, opt) {
    return this.cata({Some: x => new Some(f(x)), None: () => this}, opt);
  }
};

class Some extends Option {
  constructor(x) {
    super(x);
    this.x = x;
  }
};

class None extends Option {
  constructor() {
    super();
  }
};


// ad-hoc polymorphic function
const map = f => t => t.map(f, t);

// helper/data

const sqr = x => x * x;

const xs = [1, 2, 3];
const x = new Some(5);
const y = new None();

// application

console.log(
  map(sqr) (xs) // [1, 4, 9]
);

console.log(
  map(sqr) (x) // Some {x: 25}
);

console.log(
  map(sqr) (y) // None {}
);

Polymorphisme de sous-type

Comme d'autres réponses couvrent déjà le polymorphisme de sous-type, je l'ignore.

Polymorphisme structural (aka sous-typage strutrual)

Le polymorphisme structural dit que différents types sont équivalents, s'ils contiennent la même structure de telle sorte qu'un type possède toutes les propriétés de l'autre, mais peut inclure des propriétés supplémentaires. Cela étant dit, le polymorphisme structural correspond à la frappe de canard au moment de la compilation et offre certainement une sécurité supplémentaire. Mais en affirmant que deux valeurs sont du même type juste parce qu'elles partagent certaines propriétés, il ignore complètement le niveau sémantique des valeurs:

const weight = {value: 90, foo: true};
const speed =  {value: 90, foo: false, bar: [1, 2, 3]};

Malheureusement, speed est considéré comme un sous-type de weight et dès que nous comparons les propriétés value, nous comparons pratiquement les pommes avec les oranges.

9
user6445533

qu'Est-ce que c'est?

Poly = plusieurs, morphisme = forme ou changement de comportement.

pourquoi on en a besoin

En programmation, il est utilisé lorsque nous voulons que l'interface d'une fonction (disons une fonction X) soit suffisamment souple pour accepter différents types ou nombre de paramètres. En outre, en fonction de la modification des types de paramètres ou des nombres, nous pourrions souhaiter que la fonction X se comporte différemment (morphisme).

Comment ça fonctionne?

Nous écrivons plusieurs implémentations de la fonction X où chaque implémentation accepte différents types de paramètres ou nombre de paramètres. En fonction du type ou du nombre de paramètres, le compilateur (au moment de l'exécution) décide quelle implémentation de X doit être exécutée lorsque X est appelé à partir d'un code.

comment puis-je obtenir ce comportement polymorphe en javascript?

JS n’est pas un langage typé, il n’a donc pas pour vocation d’utiliser OOP des concepts tels que le polymorphisme. Cependant, la nouvelle version de JS inclut désormais des classes et il est également possible que le polymosphisme prenne tout son sens dans JS. D'autres réponses fournissent des solutions de contournement intéressantes.

7
hadaytullah

JavaScript est un langage interprété, pas un langage compilé.

Polymorhisme à la compilation (ou polymorphisme statique) Le polymorphisme à la compilation n'est rien d'autre que la surcharge de méthodes en Java, c ++

Donc, la surcharge de méthode n'est pas possible en javascript.

Mais le polymorphisme dynamique (exécution) est le polymorphisme existant au moment de l'exécution, de sorte que le remplacement de méthode est possible en javascript.

un autre exemple est PHP.

2
Apoorv

Polymorphisme signifie que la possibilité d'appeler la même méthode sur différents objets et que chaque objet répond de manière différente s'appelle POLYMORPHISM.

    function Animal(sound){
    this.sound=sound;
    this.speak=function(){
                        return this.sound;
        }
    }
//one method 
    function showInfo(obj){
                console.log(obj.speak());
    }
//different objects
    var dog = new Animal("woof");
    var cat = new Animal("meow");
    var cow = new Animal("humbow");
//responds different ways
    showInfo(dog);
    showInfo(cat);
    showInfo(cow);
0
SooRaj Patil