Ruby 中抽象类的替代品?
我是红宝石新手。一个简单的例子,我需要什么:
class Animal
abstract eat()
class Cat < Animal
eat():
implementation
class Dog < Animal
eat():
implementation
换句话说,所有扩展 Animal 的类都应该需要 eat() 方法。
在 JAVA 中,我只会使用抽象类,但经过一些研究,我发现很多人不在 Ruby 中使用它,而是推荐使用 mixin / 模块。
但是,我不明白,模块是否可以做的不仅仅是包含附加方法。确切地说,模块是否可以为类设置必须实现哪些方法的要求(如果是的话,将不胜感激)?
总而言之,在这种情况下,当我想确定同一类型的所有类都有特定的方法并以自己的方式实现它们时,我应该使用什么?
I am new to Ruby. A simple example, what I need:
class Animal
abstract eat()
class Cat < Animal
eat():
implementation
class Dog < Animal
eat():
implementation
In other words, the eat() method should be required for all the classes which extend Animal.
In JAVA I would just use an abstract class, but after doing some research I found that many people don't use it in Ruby and mixin / modules are recommended instead.
However, I don't understand, if modules can do more than just include an addition methods. To be exact, can modules set the requirements for classes which methods they must implement (if yes, an example would be appreciated)?
To sum up, what should I use in this case, when I want to be sure, that all classes of the same type have particular methods and implement them in their own way?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
使用定义必须实现的方法的模块。
Use a module which defines the methods that must be implemented.
Ruby 不提供此功能,不。您有责任确保您的类实现了它们应该实现的内容。
Ruby 无法实现此类功能的部分原因是 Ruby 类可以重新打开,并且 Ruby 支持在运行时加载任意代码,因此在尝试调用某个类之前,我们无法知道该类是否实现了某个接口。
假设
Animal
必须有一个eat
方法,我执行以下操作:在该文件末尾,
Cat
将拥有其>eat
定义,因为 Ruby 类可以多次重新打开和修改。在第一个定义之后代码是否会因为eat
尚未定义而出错?这种实施弊大于利,因为重新开课是很常见的,即使这个例子是人为的。一旦eat
方法被调用并且不存在,它是否应该出错,以便我们可以确定它在我们需要时已被定义?好吧,如果缺少该方法,无论如何都会发生这种情况。解释器永远无法知道另一个类定义是否即将到来,因此在实际调用该方法之前它永远不会中断您的工作。简而言之,超类根本不可能要求在 Ruby 中定义方法,因为类的动态本质与这样的目标相矛盾。
对不起!不过,单元测试可能会在这个地方派上用场,以确保您的子类无论如何都能完成它们应该做的事情。
Ruby does not offer this functionality, no. You are responsible for making sure that your classes implement what they ought to implement.
Part of the reason that such functionality is impossible for Ruby is that Ruby classes can be reopened, and Ruby supports loading arbitrary code at runtime, so we can't know whether a class implements a certain interface until we try to call it.
Supposing an
Animal
must have aneat
method, and I do the following:By the end of that file, the
Cat
will have itseat
definition, because Ruby classes can reopened and modified multiple times. Should the code error out after the first definition becauseeat
wasn't defined yet? That implementation would hurt more than it would help, since reopening classes is common, even if this example is contrived. Should it error out once theeat
method is called and does not exist, so we can be certain that it's defined once we need it? Well, if the method were missing, that would happen, anyway. The interpreter can never know if another class definition is on the way, so it can never cut you off until the method is actually called.In short, superclasses simply cannot possibly require a method to be defined in Ruby, because the dynamic nature of classes contradict such a goal.
Sorry! This is a place where unit testing might come in handy, though, to ensure that your subclasses do what they're supposed to be doing, anyway.
您可以只使用空方法,或者让它们引发错误以强制子类实现它们。
缺点是这只会在实际调用该方法时强制执行。 Ruby 是一种动态语言,它没有任何编译时检查。
Yo can just use empty methods, or make them raise errors to force subclasses to implement them.
The down side is this will only enforce it when the method is actually called. Ruby is a dynamic language and it doesn't have any compile-time checking.
Ruby 中没有与抽象类等效的东西。这主要是因为 Ruby 是动态类型的,这意味着抽象类的概念并不真正适用。
There's no equivalent to abstract classes in Ruby. Mostly this is because Ruby is dynamically typed, which means that the concept of abstract classes doesn't really apply.
如果你真的想实现抽象,那么你可以使用抽象 gem。
引用示例 Abstraction gem WIKI 中的示例。
If you really want to implement abstraction then you use abstraction gem.
Referencing example Example from Abstraction gem WIKI.