我目前正在尝试 Ruby 和 Rails,其中在教程和书籍中遇到了一些关于元编程的部分。很多人提到它是 Ruby 的一个必不可少的组成部分,但他们并没有详细解释。似乎元编程是 Ruby 程序员的最后一块领地。作为一个 .NET 背景下的程序员,我很难理解为什么它被认为是如此有用。
- 使用元编程有哪些好处?
- 什么是特殊类(eigenclass),它与单例模式有何不同?
- 在什么情况下通常会使用元编程?
- 在使用代码修改其他代码的行为时,尤其是不属于你自己的代码时,有哪些伦理方面的考虑?
我目前正在尝试 Ruby 和 Rails,其中在教程和书籍中遇到了一些关于元编程的部分。很多人提到它是 Ruby 的一个必不可少的组成部分,但他们并没有详细解释。似乎元编程是 Ruby 程序员的最后一块领地。作为一个 .NET 背景下的程序员,我很难理解为什么它被认为是如此有用。
使用元编程有哪些好处?
使用元编程可以创建比不使用更具表现力的API(例如,ActiveRecord使用元编程根据表的列名定义访问器方法,因此您可以像person.age
这样编写代码,而不是像person.read_attribute("age")
这样写,其中person
是一个Active Record对象,而people
表中有一个名为age
的列),并且您可以以比通常更少的代码完成一些任务。
什么是特殊类(eigenclass),它与单例(singleton)有何区别?
在Ruby语言中,“特殊类”和“单例类”这两个术语可以互换使用。
在哪些情况下使用元编程很常见?
在需要大量样板代码或创建DSL时使用元编程。
使用案例示例 1:
例如,不要编写类似以下样板代码:
class Foo
def bar
@bar
end
def bar=(b)
@bar = b
end
def baz
@baz
end
def baz=(b)
@baz = b
end
end
你可以使用元编程方法attr_accessor
来编写更短的代码,它会自动定义基于你提供的参数的getter和setter方法的名称:class Foo
attr_accessor :foo, :bar
end
如果标准库中不存在attr_accessor
,你可以像这样自己定义它(让你了解Ruby元编程的样子):
class Module
def attr_accessor(*variable_names)
variable_names.each do |variable_name|
define_method( variable_name ) do
instance_variable_get( "@#{ variable_name }" )
end
define_method( "#{ variable_name }=" ) do |value|
instance_variable_set( "@#{ variable_name }", value)
end
end
end
结束
在使用代码修改其他代码的行为,特别是不属于你的代码时,有哪些伦理上的影响?
没有。
元编程有其适用的时间和场合。我认为它在Ruby书籍中被广泛提及,是因为人们喜欢展示Ruby在其他语言无法胜任的领域所能做到的。
元编程就像不知道日语中“汉堡”或者“面条汤”的单词,但是知道“这个请”(“kore o kudasai”),并且能够在菜单上指出想要的食品一样。它提供了更多的灵活性,但你需要更多的上下文来确切地知道正在处理什么。
如果你正在创建ActiveRecord,它允许你进行find_by_foo
操作,那么元编程就是有意义的。
如果你正在编写一个突变测试库,例如zombie-chaser,或者一个对Ruby的不同实现进行特征测试的应用程序,例如Small Eigen Collider,那么元编程就是有意义的。
然而,如果你正在编写一个应用程序,那么通常不应该进行元编程,而是进行编程。例如,如果您在应用程序中使用了instance_variable_set
,那么这更像是一种代码异味,而不是您熟练程度的指标。
attr_accessor
的例子,因为它展示了强大的元编程能力的重要好处:元编程使语言本身保持简单。在另一种语言中,attr_accessor
很容易成为一个独立的语言构造(相关:C#中的属性等)。在Ruby中,它只是另一个方法。 - Mladen Jablanovićsingleton_class
、singleton_methods
和define_singleton_method
。 - Marc-André Lafortune