undef – 你为什么要在ruby中取消定义一个方法?

在任何其他编程语言中,我从未见过undef – 或任何其他允许你取消定义方法的东西。 为什么Ruby需要它?

编辑:我不是在争论这个有什么问题。 我只是不明白在运行时定义方法的目的? 那是什么意思? 怎么用? 我从来没有用C或Java做过这个。

Ruby中还有一个需要undeffunction的空白类模式。

我们的想法是从新类中删除每个方法,以便您对其进行的每个调用都以#method_missing结束。 通过这种方式,您可以实现一个真正的代理,只需将所有内容随机播放。 使用它实现装饰器模式大约是十行代码,无论目标类有多大。

如果你想看看这个习惯用法看看Ruby的一个模拟框架,他们就会使用它。 有点像flexmock 。

另一个例子是基于某些条件动态地将函数添加到类中。 在游戏中,您可以在玩家对象上添加一个#attack方法,然后在他瘫痪时将其取走,而不是使用布尔标志。 这样,调用类可以检查方法的可用性而不是标志。 我并不是说这是一个好主意,只是因为它成为可能而且有更聪明的人,然后我想出了有用的东西来做这件事。

在运行时定义方法,类和对象是Ruby的一个非常好的特性。 它允许你扩展类(记住它们是“开放的”)。 如果你看一下Rails,它有一个#find方法来查找模型中的对象,但你也可以使用find_by_user ; 该方法不存在(因此#method_missing )但在运行时创建。

如果要创建域特定语言或DSL,使用#missing_method可能很有用。

与在运行时定义方法相关的是根据需要包含模块的技术。 我在Rails应用程序上工作,有时我们必须以各种格式导出数据。 99%的情况下,Form对象不需要与导出相关的方法,但在我们的导出Rake任务中,我们执行以下操作:

 Form.send(:include, FormExportingMethods) 

所以只有在需要时才有这些方法。

这种活力是我喜欢Ruby的一个方面。 在某些语言中,你必须预先定义你的类和对象,而Ruby让你说“哦,我现在需要我的猪有翅膀吗?我只需要附上它们。”

请注意,在我的示例中,没有修改特定的表单对象; Form类是。 这是有效的,因为当您向对象发送消息时,它会在您询问的那一刻在其方法查找链中搜索响应。 因此,您可以创建一个对象,然后在其inheritance链中的任何位置添加一个方法,然后在该对象上调用该方法,它将拥有它。 显然,必须查看每个方法调用的整个inheritance链是昂贵的,但这是对这种灵活性的权衡。

您可以查看所有Rails,了解在运行时定义方法的示例(也称为元编程)。 通过在类定义中调用一个方法,它可以为该类的所有实例定义一大堆方法……

如果将单表inheritance与ORM一起使用(例如ActiveRecord),则可能需要取消定义未用于特定类/对象的字段的方法。

 # table: shapes, with columns: name, sides, radius, type class Shape < ActiveRecord::Base end class Circle < Shape end class Square < Shape undefine_method :radius end 

注意:这实际上不适用于ActiveRecord,因为它在内部期望始终定义每个字段的方法。

注意:正方形确实有一个半径,它只是不常用,但你得到了要点? 想想你在数据库中存储圆圈所具有的某些属性,但Square不会。

我正在使用外部API,其中一个JSON响应包含一个名为“methods”的字段。 我正在围绕json创建一个OpenStruct,只是为了让json更易于管理。 调用openStruct.methods时,它返回Object实例方法“methods”的结果。

所以我做了:

 class MyOpenStruct < OpenStruct def methods end undef :methods end openStruct = OpenStruct.new(my_json) 

我见过这个与Mixins一起使用; 所以你可以包括整个事情,然后取消它不应该支持的方法..例如ruby图形库鞋 。

button类混合在clickable模块中,然后undefrelease方法,因为按钮不支持它。

另一个简单的例子,所以它可以在这里找到:

 module Walkable attr_accessor :location def walk(steps) @location += steps end def walk_back(steps) @location -= steps end end class Zombie include Walkable undef walk_back #zombies can only walk forwards end