C# 如何在Ruby中实现多态性?

C# 如何在Ruby中实现多态性?,c#,ruby,polymorphism,C#,Ruby,Polymorphism,在C#中,我可以这样做: 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) {

在C#中,我可以这样做:

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!";
    }
}
类程序
{
静态void Main(字符串[]参数)
{
列出动物=新列表();
添加(新狗());
添加(新的Cat());
foreach(动物中的动物a)
{
Console.WriteLine(a.MakeNoise());
a、 睡眠();
}
}
}
公营动物
{
公共虚拟字符串MakeNoise(){return string.Empty;}
公众睡眠
{
Writeline(this.GetType().ToString()+“正在睡眠”);
}
}
公营狗:动物
{
公共重写字符串MakeNoise()
{
回“汪!”;
}
}
公猫:动物
{
公共重写字符串MakeNoise()
{
返回“喵!”;
}
}
显然,输出是(稍加解释):

  • 狗在睡觉
  • 喵喵
  • 猫在睡觉

由于C#经常因其冗长的类型语法而受到嘲笑,因此如何在duck类型的语言(如Ruby)中处理多态性/虚拟方法?

编辑:为更新的问题添加了更多代码

免责声明:我已经一年左右没有使用Ruby了,而且这台机器上也没有安装Ruby,所以语法可能完全错误。但这些概念是正确的


对于类和重写的方法,使用完全相同的方法:

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
}
类动物
def制造噪音
返回“”
结束
def睡眠
打印self.class.name+“正在休眠。\n”
结束
结束
类狗<动物
def制造噪音
回“汪!”
结束
结束
猫类<动物类
def制造噪音
返回“喵!”
结束
结束
动物=[狗。新,猫。新]
每只动物{124; a|
打印a.MakeNoise+“\n”
a、 睡眠
}

基于前面的答案,您可能会这样做吗


澄清后的第二次切割:

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
}
类动物
def制造噪音
raise NotImplementedError#我不记得确切的错误类别
结束
def睡眠
将self.class.to_+“正在睡觉。”
结束
结束
类狗<动物
def制造噪音
回“汪!”
结束
结束
猫类<动物类
def制造噪音
返回“喵!”
结束
结束
动物=[狗。新,猫。新]
每只动物{124; a|
制造噪音
a、 睡眠
}
(我将保持原样,但“self.class.name”胜过“.to”)

使用惯用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
类动物
def睡眠
放置“#{self.class}正在睡眠”
结束
结束
类狗<动物
制造噪音
“汪!”
结束
结束
猫类<动物类
制造噪音
“喵喵!”
结束
结束
[狗,猫]。每只狗都发出咔嗒声|
动物=clazz.new
放动物。制造噪音
动物睡眠
结束

我会这样写:

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
类动物
def发出噪音;''结束
def睡眠;放置“#{self.class.name}正在睡眠。”结束
结束
狗类<动物类;def发出噪音;'汪结束
猫类<动物类;def发出噪音;'喵喵结束
[狗,新的,猫,新的],每只都是动物|
放动物。制造噪音
动物睡眠
结束
它与其他解决方案没有什么不同,但这是我更喜欢的风格


这是12行而不是原始C#示例中的41行(实际上,可以使用集合初始值设定项删除3行)。不错

到目前为止,我觉得所有的答案都很好。我想我应该提一下,整个继承的事情并不是完全必要的。暂时不考虑“睡眠”行为,我们可以使用duck类型实现整个预期结果,而完全不需要创建动物基类。谷歌搜索“鸭子打字”应该可以给出很多解释,所以在这里让我们说“如果它走路像鸭子,嘎嘎叫像鸭子……”

“睡眠”行为可以通过使用mixin模块来提供,比如Array、Hash和其他Ruby内置类inclue Enumerable。我并不是说它一定更好,只是一种不同的、也许更习惯于Ruby的方式

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

你知道其余的…

duck类型的原理就是对象必须响应被调用的方法。因此,类似的事情可能也会起作用:

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
模块休眠
def睡眠;放置“#{self}睡眠”
结束
dog=“dog”
狗。延长睡眠时间

类是manveru解决方案的一个小变种,它基于类类型数组动态创建不同类型的对象。其实没什么不同,只是更清楚一点

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

有一个方法
变成了
,它实现了多态性(通过将给定类中的所有实例变量处理为新类)

  • 多态性有助于避免
    if
    语句()

  • 如果使用
    RubyOnRails
    变为
    方法已实现:

  • 快速提示:如果您将多态性与之混合,它将为您带来重构代码的最有效组合


我希望它能帮助你

你提到了“真正的”多态性。你对“真实”的定义是什么?对不起,Ruby的什么版本是“类猫:动物”?是不是“Brent:那将是“一个Python用户记住的Ruby”,那么class.name会输出动物还是狗?我真的很好奇。是的,哈哈,我有时会做“一个Ruby用户记住的Python”“Pythonic的反面是什么?Rubenesque?我不是Ruby大师,但是
put
不输出字符串吗?如果是这样的话,这个例子在调用
sleep
时调用它两次——一次在方法中,一次使用它的返回值(不管是什么!)你是对的,
put
返回
nil
,因此外部
put
将简单地
打印一个新行,相当于
print({nil}\n”)
,这与打印(“\n”)
相同。我没有注意到输出中的尾随换行符,对此表示抱歉。它应该是
put animal.make_noise;动物。睡眠
,而不是将动物。睡眠
制造噪音
制造噪音
相对?使用
返回
?为什么不追随Ruby公司呢
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
Dog with name Spot becomes Cat
and makes a noise: Meow
----
Cat with name Tom becomes Cat
and makes a noise: Meow
----