En C#, puedo hacer esto:

class Program
{
    static void Main(string[] args)
    {
        List<Animal> animals = new List<Animal>();

        animals.Add(new Dog());
        animals.Add(new Cat());

        foreach (Animal a in animals)
        {
            Console.WriteLine(a.MakeNoise());
            a.Sleep();
        }
    }
}

public class Animal
{
    public virtual string MakeNoise() { return String.Empty; }
    public void Sleep()
    {
        Console.Writeline(this.GetType().ToString() + " is sleeping.");
    }
}

public class Dog : Animal
{
    public override string MakeNoise()
    {
        return "Woof!";
    }
}

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

Obviamente, el resultado es (Ligeramente parafraseado):

  • Trama
  • Perro está Durmiendo
  • Miau
  • Gato está Durmiendo

Ya que C# es a menudo ridiculizado por su detallado el tipo de sintaxis, ¿cómo manejar el polimorfismo/métodos virtuales en un pato de lenguaje escrito, tales como Ruby?

Usted ha hablado de “real” polimorfismo. ¿Cuál es tu definición de “real” me dejo el mío: en.wikipedia.org/wiki/…

OriginalEl autor FlySwat | 2008-09-26

8 Comentarios

  1. 15

    edit: añadido más de código para su actualizado pregunta

    descargo de responsabilidad: yo no he utilizado Ruby en un año o así, y no lo tengo instalado en esta máquina, por lo que la sintaxis puede ser del todo malo. Pero los conceptos son correctos.


    Exactamente de la misma manera, con las clases y los métodos sobrescritos:

    class Animal
        def MakeNoise
            return ""
        end
        def Sleep
            print self.class.name + " is sleeping.\n"
        end
    end
    
    class Dog < Animal
        def MakeNoise
            return "Woof!"
        end
    end
    
    class Cat < Animal
        def MakeNoise
            return "Meow!"
        end
    end
    
    animals = [Dog.new, Cat.new]
    animals.each {|a|
        print a.MakeNoise + "\n"
        a.Sleep
    }
    Lo siento, pero ¿qué versión de Ruby es “class Gato : Animal”? ¿No es “<” por herencia?
    Brent: que sería “Ruby recordado por una Pitón de usuario”
    Así, la voluntad de la clase.nombre de la salida de los Animales o Perro? Estoy realmente curioso.
    Es la salida de “Perro”.
    Yep LOL, a veces lo hago “Python como recordado por un Rubí de usuario” ¿Qué es la inversa de Python? Rubenesque?

    OriginalEl autor John Millikin

  2. 22

    Todas las respuestas que hasta ahora se ven bastante bien para mí. He pensado que me gustaría mencionar que la totalidad de la herencia, cosa que no es totalmente necesario. Excluyendo el “sueño” de comportamiento por un momento, podemos lograr todo el resultado deseado con el uso del pato-escribir y omitiendo la necesidad de crear un Animal de la clase base. Buscando en google por “duck-typing” debe producir cualquier número de explicaciones, así que por aquí vamos a decir “si camina como un pato y grazna como un pato…”

    El “sueño” comportamiento podría ser proporcionada por el uso de un mixin módulo, como Matriz, Hash y otros Ruby clases incorporadas inclue Enumerable. No estoy sugiriendo es necesariamente mejor, sólo diferente y tal vez más idiomáticamente Ruby manera de hacerlo.

    module Animal
      def sleep
        puts self.class.name + " sleeps"
      end
    end
    
    class Dog
      include Animal
      def make_noise
        puts "Woof"
      end
    end
    
    class Cat
      include Animal
      def make_noise
        puts "Meow"
      end
    end

    Ya saben el resto…

    +1 para mezclar-en la funcionalidad común en lugar de heredar de ella. Mientras tanto los métodos de trabajo, esto es más de “el Rubí manera de hacerlo” (para este ejemplo).
    Es curioso que en CRuby, esto es casi equivalente a la herencia: incluyendo el módulo de animal establece la superclase de Perro a ser los animales, y la anterior de la superclase de Perro a la superclase de los Animales. Aunque esto funciona, y puede ser “el rubí manera de hacerlo”, uno debe tener en cuenta que esto es mucho menos eficiente que la de heredar: CRuby hace una copia del módulo para cada clase, incluyendo (por la razón indicada anteriormente).

    OriginalEl autor Mike Woodhouse

  3. 10

    El uso de modismos, Ruby

    class Animal
      def sleep
        puts "#{self.class} is sleeping"
      end
    end
    
    class Dog < Animal
      def make_noise
        "Woof!"
      end
    end
    
    class Cat < Animal
      def make_noise
        "Meow!"
      end
    end
    
    [Dog, Cat].each do |clazz|
      animal = clazz.new
      puts animal.make_noise
      animal.sleep
    end
    Yo no soy un Rubí gurú, pero no puts la cadena de salida? Si es así, en este ejemplo se llama dos veces cuando se llama a sleep – una vez dentro del método, y una vez con su valor de retorno (lo que sería!)
    Tienes razón, y puts devuelve nil, por lo que el exterior puts simplemente print una nueva línea, equivalente a print("#{nil}\n"), que es la misma que print("\n"). Yo no noto la final de salto de línea en mi salida, lo siento.
    Debe ser puts animal.make_noise; animal.sleep, no puts animal.sleep
    Gracias, actualizado.

    OriginalEl autor manveru

  4. 2

    Edificio en la respuesta anterior, ¿es esta la forma podría hacerlo?


    Segundo corte después de la aclaración:

    class Animal
        def MakeNoise
            raise NotImplementedError # I don't remember the exact error class
        end
        def Sleep
            puts self.class.to_s + " is sleeping."
        end
    end
    
    class Dog < Animal
        def MakeNoise
            return "Woof!"
        end
    end
    
    class Cat < Animal
        def MakeNoise
            return "Meow!"
        end
    end
    
    animals = [Dog.new, Cat.new]
    animals.each {|a|
        puts a.MakeNoise
        a.Sleep
    }

    (Voy a dejar esto como está, pero “sí.clase.nombre” se gana “.to_s”)

    MakeNoise frente a make_noise? El uso de returns? ¿Por qué no seguir Ruby convenciones?
    ¿Por qué debería seguir una convención no me gusta intensamente? En mi humilde opinión, el subrayado es feo y que impide el flujo de la lectura; CamelCase es mucho más fácil de leer. ¿De verdad el voto de mí hacia abajo sólo para eso? Meh es mi respuesta
    Usted debe seguir una convención (independientemente de su opinión de él) si estás escribiendo código que usan otras personas. Van a estar esperando CamelCase nombres para referirse a las clases y underscore_separated nombres para referirse a los métodos de la clase y no sabe nada acerca de sus pensamientos sobre la convención. Si sólo la escritura de código para leer, entonces eso es una cosa, pero si otros se van a utilizar su código, vaya con el Principio De la menor Sorpresa.
    Yo entiendo de donde vienes. De verdad que estoy diciendo dos cosas: en Primer lugar, yo realmente no creo que una desviación de la “aceptado” convenios de esto es un valor de un downvote; y segundo, que la “aceptado” las convenciones son feos y me obligan a elegir entre “estar en comunidad” y “código de la belleza” (en el ojo de la esto espectador. Sí, me devuelve, porque creo que tiene un código más claro. Sí, puedo usar CamelCase, porque creo que es más fácil de leer. Y sí, utilizo aquí porque quiero mostrar lo que creo que es lo mejor, y deja que otros juzguen.
    Yo uso a menudo return así 🙂 no estoy de acuerdo con algunas de sus opiniones sobre el estilo, pero estoy de acuerdo en que el estilo aquí no vale un downvote. +1 para una solución de trabajo, a pesar de estilo de codificación.

    OriginalEl autor Brent.Longborough

  5. 1

    El principio de pato escribir es sólo que el objeto ha de responder a los llamados métodos. Algo así como que puede hacer el truco demasiado :

    module Sleeping
      def sleep; puts "#{self} sleeps"
    end
    
    dog = "Dog"
    dog.extend Sleeping
    class << dog
      def make_noise; puts "Woof!" end
    end
    
    class Cat
      include Sleeping
      def to_s; "Cat" end
      def make_noise; puts "Meow!" end
    end
    
    [dog, Cat.new].each do |a|
      a.sleep
      a.make_noise
    end

    OriginalEl autor zimbatm

  6. 1

    Un poco variante de manveru la solución a la dinámica de crear diferentes tipo de objeto basado en una matriz de tipos de Clase. No muy diferente, sólo un poco más claro.

    Species = [Dog, Cat]
    
    Species.each do |specie|
      animal = specie.new   # this will create a different specie on each call of new
      print animal.MakeNoise + "\n"
      animal.Sleep
    end

    OriginalEl autor bitTnkr

  7. 0

    Esta es la forma en que yo iba a escribir:

    class Animal
      def make_noise; '' end
      def sleep; puts "#{self.class.name} is sleeping." end
    end
    
    class Dog < Animal; def make_noise; 'Woof!' end end
    class Cat < Animal; def make_noise; 'Meow!' end end
    
    [Dog.new, Cat.new].each do |animal|
      puts animal.make_noise
      animal.sleep
    end

    No realmente diferente de las otras soluciones, pero este es el estilo que yo prefiero.

    Que de las 12 líneas de frente al 41 líneas (en realidad, puede afeitarse 3 líneas mediante el uso de un inicializador de colección) de la original ejemplo de C#. No está mal!

    OriginalEl autor Jörg W Mittag

  8. 0

    Hay un método becomes que implementa un polimorfismo (por afrontar todas las variables de instancia de la clase dada a uno nuevo)

    class Animal
      attr_reader :name
    
      def initialize(name = nil)
        @name = name
      end
    
      def make_noise
        ''
      end
    
      def becomes(klass)
        became = klass.new
        became.instance_variables.each do |instance_variable|
          value = self.instance_variable_get(instance_variable)
          became.instance_variable_set(instance_variable, value)
        end
    
        became
      end
    end
    
    class Dog < Animal
      def make_noise
        'Woof'
      end
    end
    
    class Cat < Animal
      def make_noise
        'Meow'
      end
    end
    
    animals = [Dog.new('Spot'), Cat.new('Tom')]
    
    animals.each do |animal|
      new_animal = animal.becomes(Cat)
      puts "#{animal.class} with name #{animal.name} becomes #{new_animal.class}"
      puts "and makes a noise: #{new_animal.make_noise}"
      puts '----'
    end

    y el resultado es:

    Dog with name Spot becomes Cat
    and makes a noise: Meow
    ----
    Cat with name Tom becomes Cat
    and makes a noise: Meow
    ----
    • Un polimorfismo podría ser útil para evitar if declaración (antiifcampaign.com)

    • Si utiliza RubyOnRails becomes método ya está implementado: se convierte en

    • Sugerencias rápidas: si se mezcla el polimorfismo con STI trae la forma más eficiente combo para refactorizar el código

    Me gustaría que te ayudó

    OriginalEl autor itsnikolay

Dejar respuesta

Please enter your comment!
Please enter your name here