Pregunta

¿Cómo se puede describir el polimorfismo de una manera fácil de entender?

Podemos encontrar mucha información sobre el tema en Internet y en libros, como en Tipo polimorfismo . Pero tratemos de hacerlo lo más simple posible.

¿Fue útil?

Solución

Esto es de mi respuesta de una pregunta similar. Aquí hay un ejemplo de polimorfismo en pseudo-C # / Java:

class Animal
{
    abstract string MakeNoise ();
}

class Cat : Animal {
    string MakeNoise () {
        return "Meow";
    }
}

class Dog : Animal {
    string MakeNoise () {
        return "Bark";
    }
}

Main () {
   Animal animal = Zoo.GetAnimal ();
   Console.WriteLine (animal.MakeNoise ());
}

El método Main () no conoce el tipo de animal y depende del comportamiento de una implementación particular del método MakeNoise ().

Otros consejos

Dos objetos responden al mismo mensaje con comportamientos diferentes; el remitente no tiene que preocuparse.

Todas las latas con una simple tapa se abren de la misma manera.
Como humano, usted sabe que puede abrir () cualquier cosa que pueda encontrar.

Cuando se abren, no todas las latas se comportan de la misma manera.
Algunas contienen nueces, otras contienen serpientes falsas que salen.
El resultado depende de qué TIPO de lata, si la lata fue una "CanOfNuts" o un '' CanOfSnakes '', pero esto no tiene relación con CÓMO lo abres. Solo sabe que puede abrir cualquier lata y obtendrá algún tipo de resultado que se decidirá en función del tipo de lata que abrió.

pUnlabledCan- > Open (); // podría dar nueces, podría dar serpientes. No lo sabemos hasta que lo llamemos

Open () tiene un tipo de retorno genérico de " Contenido " (o podríamos decidir que no hay ningún tipo de retorno), de modo que open siempre tenga la misma firma de función.

Usted, el humano, es el usuario / llamante.
Open () es la función virtual / polimórfica.
" Can " es la clase base abstracta.
CanOfNuts y CanOfSnakes son los hijos polimórficos del " Can " clase.
Se pueden abrir todas las latas, pero lo que específicamente hace y qué tipo específico de contenido devuelve están definidas por qué tipo de lata es.
Todo lo que sabe cuando ve pUnlabledCan es que puede abrirlo () y devolverá el contenido. Cualquier otro comportamiento (como reventar serpientes en la cara) se decide por la lata específica.

La descripción más simple del polimorfismo es que es una forma de reducir las declaraciones if / switch .

También tiene el beneficio de permitirle extender sus declaraciones if / switch (o las de otras personas) sin modificar las clases existentes.

Por ejemplo, considere la clase Stream en .NET. Sin polimorfismo, sería una sola clase masiva en la que cada método implementa una declaración de cambio como:

public class Stream
{
    public int Read(byte[] buffer, int offset, int count)
    {
        if (this.mode == "file")
        {
            // behave like a file stream
        }
        else if (this.mode == "network")
        {
            // behave like a network stream
        }
        else // etc.
    }
}

En su lugar, permitimos que el tiempo de ejecución haga el cambio por nosotros de una manera más eficiente, eligiendo automáticamente la implementación basada en el tipo concreto ( FileStream , NetworkStream ), por ejemplo

public class FileStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a file stream
    }
}

public class NetworkStream : Stream
{
    public override int Read(byte[] buffer, int offset, int count)
    {
        // behave like a network stream
    }
}

Poli: muchos
Morfismo: formas / formas

El actor contra el personaje (o rol)

Las manzanas y las naranjas son ambas frutas. Se puede comer fruta. Por lo tanto, se pueden comer manzanas y naranjas.

¿El pateador? ¡Los comes de manera diferente! Pela las naranjas, pero no las manzanas.

Entonces, la implementación difiere, pero el resultado final es el mismo, se come la fruta .

Si camina como un pato y grazna como un pato, entonces puede tratarlo como un pato en cualquier lugar donde necesite un pato.

Este es un artículo mejor en realidad

El polimorfismo permite que los objetos se vean " lo mismo, pero se comportan de diferentes maneras. El ejemplo habitual es tomar una clase base animal con un método Speak (), una subclase de perro emitirá un ladrido mientras que una subclase de cerdo emitirá un oink.

La respuesta corta de 5 segundos que la mayoría de la gente usa para que otros desarrolladores puedan entender el polimorfismo es sobrecargar y anular

Misma sintaxis, semántica diferente.

La forma más sencilla de describirlo: un verbo que se puede aplicar a más de un tipo de objeto.

Todo lo demás, como dijo Hillel, es solo un comentario.

El polimorfismo es tratar las cosas de manera abstracta confiando en el conocimiento de un "padre" común. (piense en jerarquías como Animal como padre de perros y gatos).

Por ejemplo, todos los animales pueden respirar oxígeno, y si bien cada uno puede hacer esto de manera diferente, usted podría diseñar una instalación que proporcione oxígeno para que los animales respiren, apoyando tanto a perros como a gatos.

Como un pequeño extra, puedes hacer esto aunque Animal sea un "resumen". identificador (no hay una cosa real de "Animal", solo tipos de animales).

El polimorfismo es el almacenamiento de valores de más de un tipo en una ubicación de un solo tipo.

Tenga en cuenta que la mayoría de las otras respuestas a esta pregunta, en el momento de escribir esto, en realidad describen un despacho dinámico, no un polimorfismo.

El despacho dinámico requiere polimorfismo, pero lo contrario no es cierto. Uno podría imaginar un lenguaje muy similar a Java o C # pero cuyo System.Object no tenía miembros; Sería necesaria la conversión de texto antes de hacer algo con el valor. En este lenguaje teórico, habría polimorfismo, pero no necesariamente métodos virtuales, o cualquier otro mecanismo de despacho dinámico.

El despacho dinámico es el concepto relacionado pero distinto, bien descrito en la mayoría de las otras respuestas. Sin embargo, la forma en que normalmente funciona en lenguajes orientados a objetos (seleccionando una función basada en el primer tipo de argumento ('this' o 'Self')) no es la única forma en que puede funcionar. Despacho múltiple también es posible, donde la selección se aplica a todos los tipos de argumentos.

Del mismo modo, la resolución de sobrecarga y el despacho múltiple son análogos exactos entre sí; la resolución de sobrecarga es un despacho múltiple aplicado a tipos estáticos, mientras que el despacho múltiple es una resolución de sobrecarga aplicada a tipos de tiempo de ejecución almacenados en ubicaciones polimórficas.

El polimorfismo está dividiendo el mundo en cuadros basados ??en propiedades comunes y tratando los elementos en un cuadro dado como intercambiables cuando solo desea usar estas propiedades comunes.

El

polimorfismo es la capacidad de tratar cosas diferentes como si fueran lo mismo estableciendo una identidad compartida entre ellas y luego explotándolas.

El polimorfismo es lo que obtienes cuando el mismo método se aplica a varias clases. Por ejemplo, tanto una Cadena como una Lista pueden tener '' Invertir '' métodos Ambos métodos tienen el mismo nombre ("Reverse"). Ambos métodos hacen algo muy similar (invierten todos los caracteres o invierten el orden de los elementos en la lista). Pero la implementación de cada '' Reverse '' El método es diferente y específico para su clase. (En otras palabras, la cadena se invierte como una cadena y la lista se invierte como una lista).

Para usar una metáfora, podría decir "Preparar la cena". a un chef francés o a un chef japonés. Cada uno realizaría "preparar la cena" a su manera característica.

El resultado práctico es que podría crear un "Motor de inversión". que acepta un objeto y llama "Invertir" en eso. Mientras el objeto tenga un método inverso, su motor de inversión funcionará.

Para ampliar la analogía del chef, podría construir un " Waiterbot " que le dice a los chefs que hagan "Cena". El Waiterbot no tiene que saber qué tipo de cena se preparará. Ni siquiera tiene que asegurarse de hablar con un chef. Todo lo que importa es que el "chef" (o bombero, o máquina expendedora, o dispensador de comida para mascotas) sabe qué hacer cuando se le dice "Preparar la cena".

Lo que esto le compra como programador es menos líneas de código y enlace de seguridad de tipo o tardío. Por ejemplo, aquí hay un ejemplo con seguridad de tipo y encuadernación temprana (en un lenguaje tipo C que estoy inventando sobre la marcha):

class BankAccount {
    void SubtractMonthlyFee
}

class CheckingAccount : BankAccount {}

class SavingsAccount : BankAccount {}

AssessFee(BankAccount acct) {
    // This will work for any class derived from
    //   BankAccount; even classes that don't exist yet
    acct.SubtractMonthlyFee
}

main() {

    CheckingAccount chkAcct;
    SavingsAccount saveAcct;

    // both lines will compile, because both accounts
    //   derive from "BankAccount". If you try to pass in
    //   an object that doesn't, it won't compile, EVEN
    //   if the object has a "SubtractMonthlyFee" method.
    AssessFee(chkAcct);
    AssessFee(saveAcct);
}

Aquí hay un ejemplo sin tipo de seguridad pero con enlace tardío:

class DatabaseConnection {
    void ReleaseResources
}

class FileHandle {
    void ReleaseResources
}

FreeMemory(Object obj) {
    // This will work for any class that has a 
    //   "ReleaseResources" method (assuming all
    //   classes are ultimately derived from Object.
    obj.ReleaseResources
}

main() {

    DatabaseConnection dbConn;
    FileHandle fh;

    // You can pass in anything at all and it will
    //   compile just fine. But if you pass in an
    //   object that doesn't have a "ReleaseResources"
    //   method you'll get a run-time error.
    FreeMemory(dbConn);
    FreeMemory(fh);
    FreeMemory(acct); //FAIL! (but not until run-time)
}

Para un excelente ejemplo, mire el método .NET ToString (). Todas las clases lo tienen porque todas las clases se derivan de la clase Object. Pero cada clase puede implementar ToString () de una manera que tenga sentido por sí misma.

EDITAR: Simple! = corto, en mi humilde opinión

El polimorfismo es una funcionalidad de lenguaje que permite que el código algorítmico de alto nivel opere sin cambios en múltiples tipos de datos.

Esto se hace asegurando que las operaciones invoquen la implementación correcta para cada tipo de datos. Incluso en un contexto OOP (según la etiqueta de esta pregunta), esta "implementación correcta" puede resolverse en tiempo de compilación o en tiempo de ejecución (si su idioma admite ambos). En algunos lenguajes como C ++, el soporte proporcionado por el compilador para el polimorfismo en tiempo de ejecución (es decir, despacho virtual) es específico para OOP, mientras que otros tipos de polimorfismo también pueden operar en tipos de datos que no son objetos (es decir, no struct o class , pero pueden ser tipos integrados como int o double ).

(Los tipos de polimorfismo compatibles con C ++ se enumeran y contrastan en mi respuesta: Polimorfismo en c ++ , incluso si programa otros idiomas, es potencialmente instructivo)

La forma en que lo intento y pienso es algo que se ve igual pero puede tener una funcionalidad diferente según la instancia. Para que pueda tener un tipo

interface IJobLoader

pero dependiendo de cómo se use puede tener una funcionalidad diferente sin dejar de verse igual. Puede tener instancias para BatchJobLoader, NightlyJobLoader, etc.

Tal vez estoy muy lejos.

El término polimorfismo también puede aplicarse a las funciones de sobrecarga. Por ejemplo,

string MyFunc(ClassA anA);
string MyFunc(ClassB aB);

es un ejemplo de polimorfismo no orientado a objetos.

Es la capacidad que tienen los objetos para responder al mismo mensaje de diferentes maneras.

Por ejemplo, en lenguajes como smalltalk, Ruby, Objective-C, solo tiene que enviar el mensaje y ellos responderán.

 dao  = XmlDao.createNewInstance()    #obj 1
 dao.save( data )

 dao = RdbDao.createNewnewInstance()  #obj 2
 dao.save( data )

En este ejemplo, dos objetos diferentes respondieron de diferentes maneras a los mismos mensajes: " createNewInstance () y save (obj) "

Actúan de diferentes maneras, al mismo mensaje. En los idiomas anteriores, es posible que las clases ni siquiera estén en la misma jerarquía de clases, es suficiente que respondan al mensaje.

En lenguajes como Java, C ++, C # etc. Para asignar el objeto a una referencia de objeto, deben compartir la misma jerarquía de tipos implementando la interfaz o siendo una subclase de una clase común.

fácil ... y simple.

El polimorfismo es, con mucho, la característica más importante y relevante de la programación orientada a objetos.

Es una forma de tratar diferentes cosas que pueden hacer algo similar de la misma manera sin importar cómo lo hagan.

Digamos que tienes un juego con un montón de diferentes tipos de vehículos circulando, como automóviles, camiones, patinetas, aviones, etc. Todos pueden detenerse, pero cada vehículo se detiene de una manera diferente. Algunos vehículos pueden necesitar cambiar de marcha, y algunos pueden detenerse en frío. El polimorfismo te permite hacer esto

foreach (Vehicle v in Game.Vehicles)
{
   v.Stop();
}

La forma en que se implementa la detención se difiere a los diferentes vehículos para que su programa no tenga que preocuparse por eso.

Es solo una forma de enfriar el viejo código nuevo. Escribes alguna aplicación que acepta alguna "Forma" interactuar con métodos que otros deben implementar (ejemplo: getArea). Si a alguien se le ocurre una nueva forma de implementar esa interfaz, su antiguo código puede llamar a ese nuevo código a través del método getArea.

La capacidad de un objeto de algún tipo (p. ej., un automóvil) para actuar (p. ej., frenar) como uno de otro tipo (p. ej., un vehículo) que generalmente sugiere ascendencia común (p. ej., el automóvil es un subtipo de vehículo) en un punto la jerarquía de tipos.

El polimorfismo es la solución orientada a objetos al problema de pasar una función a otra función. En C puedes hacer

 void h() { float x=3.0; printf("%f", x); }
 void k() { int y=5; printf("%i", y); }
 void g(void (*f)()) { f(); }
 g(h);  // output 3.0
 g(k);  // output 5

En C las cosas se complican si la función depende de parámetros adicionales. Si las funciones h y k dependen de diferentes tipos de parámetros, tiene problemas y debe usar la conversión. Debe almacenar esos parámetros en una estructura de datos y pasar un puntero a esa estructura de datos a g que lo pasa a h o k. h y k convierten el puntero en un puntero a la estructura adecuada y descomprimen los datos. Muy desordenado y muy inseguro debido a posibles errores de conversión:

 void h(void *a) { float* x=(float*)a; printf("%f",*x); }
 void k(void *a) { int* y=(int*)a; printf("%i",*y); }
 void g(void (*f)(void *a),void *a) { f(a); }
 float x=3.0;
 int y=5;
 g(h,&x); // output x
 g(k,&y); // output y

Entonces inventaron el polimorfismo. h y k son promovidos a clases y las funciones reales a métodos, los parámetros son variables miembro de la clase respectiva, h o k. En lugar de pasar la función, pasa una instancia de la clase que contiene la función que desea. La instancia contiene sus propios parámetros.

class Base { virtual public void call()=0; }
class H : public Base { float x; public void call() { printf("%f",x);} } h;
class K : public Base { int y; public void call() { printf("%i",y);} } k;
void g(Base &f) { f.call(); };
h.x=3.0;
k.y=5;
g(h); // output h.x
g(k); // output k.x
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top