在任何其他编程语言中,我从未见过undef - 或任何其他允许你取消定义方法的东西。为什么在Ruby中需要它?
编辑:我并不是说这有什么不妥。我只是不明白在运行时定义方法的目的?那是什么意思?怎么用?我从来没有用C或Java做过这个。答案 0 :(得分:18)
Ruby中还有一个需要undef
功能的空白类模式。
我们的想法是从新课程中删除每个方法,以便您对其发出的每个通话都以#method_missing
结尾。通过这种方式,您可以实现一个真正的代理,只需将所有内容随机播放。无论你的目标类有多大,用这个实现装饰器模式大约有十行代码。
如果你想看到这个习惯用法看看Ruby的一个模拟框架,他们会很多地使用它。类似于flexmock。
另一个例子是基于某些条件动态地将函数添加到类中。在游戏中,您可以在玩家对象上添加#attack
方法,然后在他瘫痪时将其取走,而不是使用布尔标记。这样,调用类可以检查方法的可用性而不是标志。我并不是说这是一个好主意,只是因为这是可能的,而且有更聪明的人,然后我想出了有用的东西。
答案 1 :(得分:2)
在运行时定义方法,类和对象是Ruby的一个非常好的特性。它允许你扩展类(记住它们是“开放的”)。如果你看一下Rails,它有一个#find
方法来查找模型中的对象,但你也可以使用find_by_user
;该方法不存在(因此调用#method_missing
),但在运行时创建。
如果您想创建Domain Specific Language或DSL,使用#missing_method
会很有用。
答案 2 :(得分:1)
与在运行时定义方法相关的是根据需要包含模块的技术。我在Rails应用程序上工作,有时我们必须以各种格式导出数据。 99%的情况下,Form对象不需要与导出相关的方法,但在我们的导出Rake任务中,我们执行以下操作:
Form.send(:include, FormExportingMethods)
因此只有在需要时才有这些方法。
这种活力是我喜欢Ruby的事情之一。在某些语言中,你必须预先定义你的类和对象,而Ruby让你说“哦,我现在需要我的猪才能拥有翅膀?我只需要附上它们。”
请注意,在我的示例中,未修改特定的表单对象; Form类是。这是有效的,因为当您向对象发送消息时,它会在其方法查找链中搜索您提出的响应 。因此,您可以创建一个对象,然后在其继承链中的任何位置添加方法,然后在该对象上调用该方法,它将拥有它。显然,必须查看每个方法调用的整个继承链是昂贵的,但这是对这种灵活性的权衡。
答案 3 :(得分:1)
我见过这个与Mixins一起使用;所以你可以包括整个事物,然后取消它不应该支持的方法。 ruby图形库shoes。
button
类混合在clickable
模块中,然后undef
混合了release
方法,因为按钮不支持它。
另一个简单的例子,所以它可以在这里找到:
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
答案 4 :(得分:0)
您可以查看所有Rails,了解在运行时定义方法的示例(也称为元编程)。通过在类定义中调用一个方法,它可以为该类的所有实例定义一大堆方法......
答案 5 :(得分:0)
如果您使用带有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,因为它在内部期望始终定义每个字段的方法。
注意:正方形确实有一个半径,它只是不常用,但你得到了要点?想想你存储在Circle中的数据库中的某些属性,但Square不会。
答案 6 :(得分:0)
我正在使用外部API,其中一个JSON响应包含一个名为“methods”的字段。我正在围绕json创建一个OpenStruct,只是为了让json更易于管理。调用openStruct.methods时,它返回Object实例方法“methods”的结果。
所以我做了:
class MyOpenStruct < OpenStruct
def methods
end
undef :methods
end
openStruct = OpenStruct.new(my_json)