传递一个Class或字符串化的类名?

时间:2015-02-24 13:24:57

标签: ruby-on-rails ruby oop

在Ruby中传递类或字符串化的类名是否更好?

例如,我有一个解析器/构建器,可以确定已解析记录的类类型。我将它传递给导入器类,但我可以将类的名称作为字符串或常量传递。有没有理由不去做其中一个?

x = ParsedRecord.new(value: 1, type: MyClass)

VS

x = ParsedRecord.new(value: 2, type: 'MyClass')

进口商要么:

x.type.new

VS

x.type.constantize.new

传递类似乎更容易但是我没有看到它很多(即.Rails使你为关联的类名字符串化)。也许它与加载顺序/自动加载有关?

2 个答案:

答案 0 :(得分:2)

除非你需要延迟加载类名,否则最好直接传递常量。

原因是因为将String转换为相应的类名常量是一个额外的步骤,并将为执行添加一些开销。如果您已有类名,请将其传递给它。将它转换为字符串,然后再转换为常量是没有优势的。

原因是因为你看到在其他库中传递的字符串,是因为为了传递MyClass作为参数,必须加载类定义。在某些情况下,例如在Rails中,您正在引用一个将延迟加载的类的类名(这是rescue_from宏的典型情况)。使用String并不会强制您加载类定义,直到您有效地需要它为止。

答案 1 :(得分:2)

类就像任何其他类一样是一个对象。所以,这真的不是关于课程。

只要问问自己:你宁愿将一个对象作为参数传递,还是在一个某个范围内包含某个变量名称的String,然后再将元编程转换为一个对象?

哦,那些没有名字的课程怎么样?或者其名称与可通过的变量相对应?

a = Class.new
a.name
# => nil
# has no name

A = a
a.name
# => 'A'
# has name A, is reachable via A and a

A = nil
a.name
# => 'A'
# still has name A, but is no longer reachable via A, only a

B = a
a = nil
B.name
# => 'A'
# still has name A, but is now only reachable via B

传递类本身也允许您只创建一个内联的匿名类,例如作为单元测试的存根:

ParsedRecord.new(value: 1, type: Class.new)
ParsedRecord.new(value: 2, type: Class.new do def initialize; @foo = 42 end end)