He leído algún posible artículo que pude encontrar en Internet sobre polimorfismo . Pero creo que no pude captar del todo el significado y su importancia. La mayoría de los artículos no dicen por qué es importante y cómo puedo lograr un comportamiento polimórfico en OOP (por supuesto en JavaScript).
No puedo proporcionar ningún ejemplo de código porque no tengo la idea de cómo implementarlo, por lo que mis preguntas están a continuación:
- ¿Qué es?
- ¿Por qué lo necesitamos?
- ¿Cómo funciona?
- ¿Cómo puedo lograr este comportamiento polimórfico en javascript?
Tengo este ejemplo. Pero es fácilmente comprensible cuál será el resultado de este código. No da una idea clara sobre el polimorfismo en sí.
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);
Respuestas:
El polimorfismo es uno de los principios de la programación orientada a objetos (OOP). Es la práctica de diseñar objetos para compartir comportamientos y poder anular los comportamientos compartidos con otros específicos. El polimorfismo se aprovecha de la herencia para que esto suceda.
En OOP todo se considera modelado como un objeto. Esta abstracción se puede llevar hasta las tuercas y tornillos para un automóvil, o tan amplia como simplemente un tipo de automóvil con un año, marca y modelo.
Para tener un escenario de automóvil polimórfico, habría el tipo de automóvil base, y luego habría subclases que heredarían del automóvil y proporcionarían sus propios comportamientos además de los comportamientos básicos que tendría un automóvil. Por ejemplo, una subclase podría ser TowTruck, que todavía tendría una marca y modelo de un año, pero también podría tener algunos comportamientos y propiedades adicionales que podrían ser tan básicos como una bandera para IsTowing, tan complicados como los detalles del ascensor.
Volviendo al ejemplo de las personas y los empleados, todos los empleados son personas, pero no todas las personas son empleados. Lo que quiere decir que la gente será la superclase y el empleado la subclase. Las personas pueden tener edades y pesos, pero no tienen salarios. Los empleados son personas, por lo que inherentemente tendrán una edad y un peso, pero también porque son empleados tendrán un salario.
Entonces, para facilitar esto, primero escribiremos la superclase (Persona)
function Person(age,weight){ this.age = age; this.weight = weight; }
Y le daremos a la Persona la capacidad de compartir su información.
Person.prototype.getInfo = function(){ return "I am " + this.age + " years old " + "and weighs " + this.weight +" kilo."; };
A continuación, deseamos tener una subclase de Persona, Empleado
function Employee(age,weight,salary){ this.age = age; this.weight = weight; this.salary = salary; } Employee.prototype = new Person();
Y anularemos el comportamiento de getInfo definiendo uno que sea más adecuado para un empleado
Employee.prototype.getInfo = function(){ return "I am " + this.age + " years old " + "and weighs " + this.weight +" kilo " + "and earns " + this.salary + " dollar."; };
Estos se pueden usar de manera similar a su uso de código original
var person = new Person(50,90); var employee = new Employee(43,80,50000); console.log(person.getInfo()); console.log(employee.getInfo());
Sin embargo, no se gana mucho con la herencia aquí, ya que el constructor de Employee es muy similar al de la persona y la única función en el prototipo está siendo anulada. El poder del diseño polimórfico es compartir comportamientos.
fuente
getInfo
será la del Empleado, ya que es más alta en la cadena que la de la Persona. Eso fue lo que quise decir cuando dije "anulado".return Person.prototype.getInfo.call(this) + + "and earns " + this.salary + " dollar.";
lugar de copiar y pegar el código.Como se explica en esta otra respuesta , el polimorfismo tiene diferentes interpretaciones.
La mejor explicación sobre el tema que he leído es un artículo de Luca Cardelli , un renombrado teórico de la tipografía. El artículo se llama Sobre la comprensión de tipos, abstracción de datos y polimorfismo .
¿Qué es?
Cardelli define varios tipos de polimorfismo en este artículo:
Quizás en JavaScript, es un poco más difícil ver los efectos del polimorfismo porque los tipos más clásicos de polimorfismo son más evidentes en los sistemas de tipos estáticos, mientras que JavaScript tiene un sistema de tipos dinámicos.
Entonces, por ejemplo, no hay sobrecarga de métodos o funciones o coacciones de tipo automáticas en tiempo de compilación en JavaScript. En un lenguaje dinámico, damos por sentado la mayoría de estas cosas. Tampoco necesitamos algo como el polimorfismo paramétrico en JavaScript debido a la naturaleza dinámica del lenguaje.
Aún así, JavaScript tiene una forma de herencia de tipos que emula las mismas ideas de polimorfismo de subtipo (clasificado como polimorfismo de inclusión por Cardelli anteriormente) de una manera similar a lo que normalmente hacemos en otros lenguajes de programación orientados a objetos como Java o C # (como se explica en otra respuesta que compartí arriba).
Otra forma de polimorfismo muy típica en los lenguajes dinámicos se llama tipificación de pato .
Es un error creer que el polimorfismo solo está relacionado con la programación orientada a objetos. Otros modelos de programación (funcionales, procedimentales, lógicos, etc.) ofrecen diferentes formas de polimorfismo en sus sistemas de tipos, probablemente de una manera un poco desconocida para aquellos que solo se utilizan para OOP.
¿Por qué lo necesitamos?
El polimorfismo fomenta muchos atributos buenos en el software, entre otras cosas fomenta la modularidad y la reutilización y hace que el sistema de tipos sea más flexible y maleable. Sin él, sería muy difícil razonar sobre tipos. El polimorfismo asegura que un tipo pueda ser sustituido por otros compatibles siempre que satisfagan una interfaz pública, por lo que también fomenta la ocultación de información y la modularidad.
¿Como funciona?
Esto no es fácil de responder, diferentes lenguajes tienen diferentes formas de implementarlo. En el caso de JavaScript, como se mencionó anteriormente, lo verá materializarse en forma de jerarquías de tipos usando la herencia prototípica y también puede explotarlo usando el tipo pato.
El tema es un poco amplio y abriste dos preguntas en una sola publicación. Quizás sea mejor que comiences leyendo el artículo de Cardelli y luego trates de entender el polimorfismo independientemente de cualquier lenguaje o paradigma de programación, luego comenzarás a hacer asociaciones entre los conceptos teóricos y lo que cualquier lenguaje en particular como JavaScript tiene para ofrecer para implementar esas ideas.
fuente
¿Cuál es el propósito del polimorfismo?
El polimorfismo hace que un sistema de tipo estático sea más flexible sin perder la seguridad (significativa) del tipo estático al aflojar las condiciones para la equivalencia de tipo. La prueba es que un programa solo se ejecutará si no contiene ningún error de tipo.
Una función o tipo de datos polimórficos es más general que uno monomórfico, porque se puede utilizar en una gama más amplia de escenarios. En este sentido, el polimorfismo representa la idea de generalización en lenguajes estrictamente tipificados.
¿Cómo se aplica esto a Javascript?
Javascript tiene un sistema de tipos dinámico y débil. Tal sistema de tipos es equivalente a un sistema de tipos estricto que contiene solo un tipo. Podemos pensar en un tipo como un tipo de unión enorme (pseudo sintaxis):
type T = | Undefined | Null | Number | String | Boolean | Symbol | Object | Array | Map | ...
Cada valor se asociará a uno de estos tipos de alternativas en tiempo de ejecución. Y dado que Javascript tiene un tipo débil, cada valor puede cambiar su tipo cualquier cantidad de veces.
Si tomamos una perspectiva teórica de tipos y consideramos que solo hay un tipo, podemos decir con certeza que el sistema de tipos de Javascript no tiene una noción de polimorfismo. En su lugar, tenemos tipado pato y coerción de tipo implícita.
Pero esto no debería impedirnos pensar en los tipos de nuestros programas. Debido a la falta de tipos en Javascript, necesitamos inferirlos durante el proceso de codificación. Nuestra mente debe reemplazar al compilador que falta, es decir, tan pronto como miramos un programa, debemos reconocer no solo los algoritmos, sino también los tipos subyacentes (tal vez polimórficos). Estos tipos nos ayudarán a crear programas más fiables y robustos.
Para hacer esto correctamente, les daré una descripción general de las manifestaciones más comunes del polimorfismo.
Polimorfismo paramétrico (también conocido como genéricos)
El polimorfismo paramétrico dice que los diferentes tipos son intercambiables porque los tipos no importan en absoluto. Una función que defina uno o más parámetros de tipo polimórfico paramétrico no debe saber nada de los argumentos correspondientes pero tratarlos de igual forma, porque pueden adoptar a cualquier tipo. Esto es bastante restrictivo, porque dicha función solo puede trabajar con aquellas propiedades de sus argumentos que no son parte de sus datos:
// 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"]
Polimorfismo ad-hoc (también conocido como sobrecarga)
El polimorfismo ad-hoc dice que los diferentes tipos son equivalentes solo para un propósito específico. Para ser equivalente en este sentido, un tipo debe implementar un conjunto de funciones específicas para ese propósito. Una función que define uno o más parámetros de tipo polimórfico ad-hoc necesita saber qué conjuntos de funciones están asociados a cada uno de sus argumentos.
El polimorfismo ad-hoc hace que una función sea compatible con un dominio de tipos más amplio. El siguiente ejemplo ilustra el propósito de la "asignación" y cómo los tipos pueden implementar esta restricción. En lugar de un conjunto de funciones, la restricción "asignable" solo incluye una única
map
función:// 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 {} );
Polimorfismo de subtipo
Dado que otras respuestas ya cubren el polimorfismo de subtipo, lo omito.
Polimorfismo estructural (también conocido como subtipo estructural)
El polimorfismo estructural dice que diferentes tipos son equivalentes, si contienen la misma estructura de tal manera que un tipo tiene todas las propiedades del otro pero puede incluir propiedades adicionales. Dicho esto, el polimorfismo estructural consiste en escribir pato en tiempo de compilación y ciertamente ofrece cierta seguridad de tipo adicional. Pero al afirmar que dos valores son del mismo tipo solo porque comparten algunas propiedades, ignora por completo el nivel semántico de valores:
const weight = {value: 90, foo: true}; const speed = {value: 90, foo: false, bar: [1, 2, 3]};
Desafortunadamente,
speed
se considera un subtipo deweight
y tan pronto como comparamos lasvalue
propiedades, estamos comparando virtualmente manzanas con naranjas.fuente
len
. O quizásconj
de clojure.Poli = muchos, morfismo = cambio de forma o comportamiento.
En programación, se usa cuando queremos que la interfaz de una función (digamos la función X) sea lo suficientemente flexible como para aceptar diferentes tipos o cantidad de parámetros. Además, según los tipos o números de parámetros cambiantes, es posible que deseemos que la función X se comporte de manera diferente (morfismo).
Escribimos múltiples implementaciones de la función X donde cada implementación acepta diferentes tipos de parámetros o número de parámetros. Según el tipo o número de parámetro, el compilador (en tiempo de ejecución) decide qué implementación de X debe ejecutarse cuando se llama a X desde algún código.
JS no es un lenguaje mecanografiado, por lo que en realidad no está destinado a utilizar conceptos de programación orientada a objetos como polimorfismo. Sin embargo, la versión más reciente de JS ahora incluye clases y existe la posibilidad de que el polimisfismo también comience a tener sentido en JS. Otras respuestas proporcionan algunas soluciones alternativas interesantes.
fuente
Polimorfismo significa Habilidad de llamar al mismo método en diferentes objetos y cada objeto responde de manera diferente se llama POLIMORFISMO .
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);
fuente
JavaScript es un lenguaje interpretado, no un lenguaje compilado.
Polimorfismo en tiempo de compilación (o polimorfismo estático) El polimorfismo en tiempo de compilación no es más que la sobrecarga de métodos en java, c ++
Entonces, la sobrecarga de métodos no es posible en javascript.
Pero el polimorfismo dinámico (en tiempo de ejecución) es el polimorfismo que existía en el tiempo de ejecución, por lo que es posible anular el método en javascript
otro ejemplo es PHP.
fuente