在ruby中定义全局方法的方法

时间:2011-08-25 09:36:12

标签: ruby global

我正在写一个小宝石,我想要定义类似DSL的方法,与 Rake 中的desctask方法几乎相同。

Rake将它们定义为Rake::DSL模块中的私有方法,然后

self.extend Rake::DSL

将模块混合到主对象中? (我是新手,如果我错了就继续笑)

这样做有什么好处?是因为将这些方法设为私有可以阻止任何其他对象使用它们(也就是说,为了防止类似some_obj.desc)?

如果我在Kernel

中定义方法会怎么样?
module Kernel
  private

  include Rake::DSL
end

有什么不同吗?

2 个答案:

答案 0 :(得分:5)

如果在Kernel模块中定义私有方法,它将在整个项目中可用。您还将重写项目用于定义rake任务的desc方法。但是如果你在你的子模块中编写你的方法,然后在超类或某个模块中扩展它 - 你可以轻松地编写任何类型的DSL lang,就像你在RakeRSpec中看到的那样。 附:使方法private阻止其他moludes或类(但不是子类)使用它们(但不是owerwrite) - 我的意思是模块嵌套层次结构。

答案 1 :(得分:3)

只是为了扩展bor1s给出的关于私有方法的答案:

在红宝石中,你有“私人”和“受保护”的方法。在讨论“受保护”方法时,bor1s所说的是正确的。声明方法“私有”还会阻止同一类的其他实例使用该方法。

当你调用“私人”方法时,你不能在它前面使用一个点 - 你甚至不能使用self.,即使使用或省略self通常具有相同的效果。

class Xyzzy
  private
  def foo
    puts "Foo called"
  end

  public
  def do_it
    foo       # <= Is OK
    self.foo  # <= raises NoMethodError
  end
end

Xyzzy.new.do_it

如果您在上面的代码中将'private'更改为'protected',则不会引发任何错误。

关于模块:

Kernel中定义方法并使用某个模块中定义的方法扩展Kernel的最终结果是相同的:在这两种情况下,该方法都是全局的。

使用模块只是更优雅,因为它将你的更改分组到一个地方,但我认为这是个人品味的问题。

通常你不在Kernel或Object中包含方法(因为它可能有点危险),但你包含(或扩展)需要这些方法的特定类或对象,在这种情况下你需要< / em>您的方法分组在一个模块中。

甚至版本0.9.0中的Rake也停止在对象中包含DSL命令:

  

==版本0.9.0

     
      
  • 不兼容 *更改*:Rake DSL命令('任务','文件'等)是   不再是Object中的私有方法。如果你需要在里面调用'task:xzy'   你的班级,包括Rake :: DSL。 DSL仍可在   顶级范围(通过扩展Rake :: DSL的顶级对象)。
  •