我是Ruby新手。一个简单的例子,我需要的是:
class Animal
abstract eat()
class Cat < Animal
eat():
implementation
class Dog < Animal
eat():
implementation
换句话说,所有扩展Animal的类都需要eat()方法。
在JAVA中,我只使用一个抽象类,但经过一些研究后我发现很多人不会在Ruby中使用它,而建议使用mixin / modules。
但是,我不明白,如果模块可以做的不仅仅是包含一个附加方法。确切地说,模块是否可以为类设置它们必须实现的方法(如果是,可以赞赏一个例子)?
总而言之,在这种情况下,我应该使用什么,当我想确定,所有相同类型的类都有特定的方法并以自己的方式实现它们?
答案 0 :(得分: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
答案 1 :(得分: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
在该文件的末尾,Cat
将具有其eat
定义,因为Ruby类可以多次重新打开和修改。由于eat
尚未定义,第一个定义后代码是否会出错?由于重新开放课程很常见,即使这个例子是人为设计的,这种实施方式的伤害也会超过它的帮助。一旦eat
方法被调用并且不存在,它是否会出错,所以我们可以确定它是在我们需要它时定义的吗?好吧,如果方法丢失了,无论如何都会发生 。解释器永远不会知道另一个类定义是否正在进行中,因此在实际调用该方法之前它永远无法阻止你。
简而言之,超类根本不可能要求在Ruby中定义一个方法,因为类的动态性质与这样的目标相矛盾。
抱歉!不过,这是一个单元测试可能会派上用场的地方,以确保您的子类能够完成他们应该做的事情。
答案 2 :(得分:2)
Yo可以使用空方法,或者让它们引发错误以强制子类实现它们。
class Base
def abstract_method
end
def mandatory_abstract_method
raise NotImplementedError.new("You must implement this")
end
end
缺点是这只会在实际调用方法时强制执行。 Ruby是一种动态语言,它没有任何编译时检查。
答案 3 :(得分:1)
Ruby中没有与抽象类相同的东西。这主要是因为Ruby是动态类型的,这意味着抽象类的概念并不真正适用。
答案 4 :(得分:0)
如果你真的想实现抽象,那么你使用抽象gem。
sudo gem install abstraction
引用Abstraction gem WIKI中的示例示例。
class Car
abstract
def go_forward
# ...
end
end
Car.new
> AbstractClassError: Car is an abstract class and cannot be instantiated
class Convertible < Car
def door_count
2
end
end
class Sedan < Car
def door_count
4
end
end
Convertible.new # => #<Convertible:0x8fdf4>