Ruby中抽象类的替代方案?

krn*_*krn 9 ruby abstract-class mixins

我是Ruby的新手.一个简单的例子,我需要的:

class Animal
   abstract eat()

class Cat < Animal
   eat():
     implementation

class Dog < Animal
   eat():
     implementation
Run Code Online (Sandbox Code Playgroud)

换句话说,所有扩展Animal的类都需要eat()方法.

在JAVA中我只使用一个抽象类,但经过一些研究后我发现许多人不在Ruby中使用它,而建议使用mixin/modules.

但是,我不明白,如果模块可以做的不仅仅是包含一个额外的方法.确切地说,模块是否可以为类必须实现哪些方法设置要求(如果是,可以赞赏一个例子)?

总而言之,在这种情况下我应该使用什么,当我想确定,所有相同类型的类都有特定的方法并以自己的方式实现它们?

Tat*_*son 19

使用定义必须实现的方法的模块.

module Animal
  def eat
    raise NotImplementedError
  end
end

class Cat
  include Animal

  def eat
    "Om nom nom"
  end
end

class Dog
  include Animal
end

c = Cat.new
c.eat # => "Om nom nom"

d = Dog.new
d.eat # => NotImplementedError
Run Code Online (Sandbox Code Playgroud)


Mat*_*chu 9

Ruby不提供此功能,不.您有责任确保您的类实现他们应该实现的内容.

Ruby不可能实现这样的功能的部分原因是Ruby类可以重新打开,Ruby支持在运行时加载任意代码,因此在我们尝试调用它之前,我们无法知道类是否实现了某个接口.

假设Animal必须有一个eat方法,我会做以下事情:

class Cat < Animal
  def talk
    puts "meow"
  end
end

class Cat
  def eat
    puts "om nom nom"
  end
end
Run Code Online (Sandbox Code Playgroud)

在该文件的末尾,Cat将具有其eat定义,因为Ruby类可以多次重新打开和修改.如果代码在第一个定义之后出错,因为eat尚未定义?由于重新开放课程很常见,即使这个例子是人为设计的,这种实施方式的伤害也会超过它的帮助.如果eat方法被调用并且不存在,它是否应该出错,那么我们可以确定它是在我们需要它时定义的吗?好吧,如果方法丢失了,那么无论如何都会发生.解释器永远不会知道另一个类定义是否正在进行中,因此在实际调用该方法之前它永远无法切断.

简而言之,超类根本不可能要求在Ruby中定义方法,因为类的动态性质与这样的目标相矛盾.

抱歉! 不过,这是一个单元测试可能会派上用场的地方,以确保您的子类能够完成他们应该做的事情.