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

时间:2009-02-12 22:29:43

标签: ruby-on-rails ruby syntax

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

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

7 个答案:

答案 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)