Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How do you do polymorphism in Ruby?

In C#, I can do this:

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!";
    }
}

Obviously, the output is (Slightly paraphrased):

  • Woof
  • Dog is Sleeping
  • Meow
  • Cat is Sleeping

Since C# is often mocked for its verbose type syntax, how do you handle polymorphism/virtual methods in a duck typed language such as Ruby?

like image 384
FlySwat Avatar asked Sep 26 '08 03:09

FlySwat


People also ask

How do you use polymorphism in Ruby?

Polymorphism works well in Ruby on Rails as an Active Record association. If models essentially do the same thing, we can turn them into one single model to create a polymorphic relationship. In this example, we have an ERD for an application where a user can post an instrument with its details.

What is polymorphic Ruby?

In Ruby on Rails, a polymorphic association is an Active Record association that can connect a model to multiple other models. For example, we can use a single association to connect the Review model with the Event and Restaurant models, allowing us to connect a review with either an event or a restaurant.

How does duck typing help Ruby support polymorphism?

Polymorphism using Duck-Typing In Ruby, we focus on the object's capabilities and features rather than its class. So, Duck Typing is nothing but working on the idea of what an object can do rather than what it actually is. Or, what operations could be performed on the object rather than the class of the object.

How do you use polymorphism?

You can use polymorphism to solve this problem in two basic steps: Create a class hierarchy in which each specific shape class derives from a common base class. Use a virtual method to invoke the appropriate method on any derived class through a single call to the base class method.


2 Answers

All the answers so far look pretty good to me. I thought I'd just mention that the whole inheritance thing is not entirely necessary. Excluding the "sleep" behaviour for a moment, we can achieve the whole desired outcome using duck-typing and omitting the need to create an Animal base class at all. Googling for "duck-typing" should yield any number of explanations, so for here let's just say "if it walks like a duck and quacks like a duck..."

The "sleep" behaviour could be provided by using a mixin module, like Array, Hash and other Ruby built-in classes inclue Enumerable. I'm not suggesting it's necessarily better, just a different and perhaps more idiomatically Ruby way of doing it.

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

You know the rest...

like image 66
Mike Woodhouse Avatar answered Oct 02 '22 17:10

Mike Woodhouse


edit: added more code for your updated question

disclaimer: I haven't used Ruby in a year or so, and don't have it installed on this machine, so the syntax might be entirely wrong. But the concepts are correct.


The exact same way, with classes and overridden methods:

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
}
like image 20
John Millikin Avatar answered Oct 02 '22 16:10

John Millikin