我正在写一个小宝石,我想要定义类似DSL的方法,与 Rake 中的desc
和task
方法几乎相同。
Rake将它们定义为Rake::DSL
模块中的私有方法,然后
self.extend Rake::DSL
将模块混合到主对象中? (我是新手,如果我错了就继续笑)
这样做有什么好处?是因为将这些方法设为私有可以阻止任何其他对象使用它们(也就是说,为了防止类似some_obj.desc
)?
如果我在Kernel
module Kernel
private
include Rake::DSL
end
有什么不同吗?
答案 0 :(得分:5)
如果在Kernel
模块中定义私有方法,它将在整个项目中可用。您还将重写项目用于定义rake任务的desc
方法。但是如果你在你的子模块中编写你的方法,然后在超类或某个模块中扩展它 - 你可以轻松地编写任何类型的DSL lang,就像你在Rake
或RSpec
中看到的那样。
附:使方法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的顶级对象)。