此Ruby Style Guide表示使用self.method_name
代替class method_name
会更好。但是为什么?
class TestClass
# bad
class << self
def first_method
# body omitted
end
def second_method_etc
# body omitted
end
end
# good
def self.first_method
# body omitted
end
def self.second_method_etc
# body omitted
end
end
是否存在性能问题?
答案 0 :(得分:86)
class << self
擅长将所有类方法保存在同一个块中。如果从def self.method
开始添加方法,那么就不能保证(除了惯例和一厢情愿的想法)之后不会在文件后面隐藏一个额外的类方法。
def self.method
擅长明确说明方法是类方法,而使用class << self
则必须自己去找容器。
其中哪一个对您来说更重要是一个主观决定,也取决于其他人在处理代码的程度以及他们的偏好。
答案 1 :(得分:29)
通常,class << self
用于元编程,以将类设置为自我一段时间。如果我正在尝试编写10个方法,我会像这样使用它:
METHOD_APPENDICES = [1...10]
class << self
METHOD_APPENDICES.each do |n|
define_method("method#{n}") { n }
end
end
这将创建10个只返回数字的方法(method1,method2,method3等)。在这种情况下,我会使用class << self
来明确,因为元编程self
至关重要。在里面乱扔垃圾self.
实际上会让更少可读。
如果您只是正常定义类方法,请坚持self.class_method_name
,因为更多人可能会理解它。除非您希望观众理解它,否则无需引入元语法。
答案 2 :(得分:23)
如上所述,两种样式似乎都是等效的,但使用class << self
可以将类方法标记为private
或protected
。例如:
class UsingDefSelf
def self.a; 'public class method'; end
private
def self.b; 'public class method!'; end
end
class UsingSingletonClass
class << self
def a; 'public class method'; end
private
def b; 'private class method'; end
end
end
private
仅影响实例方法。使用单例类,我们定义该类的实例方法,它们转换为包含类的类方法!
我们还可以使用private
将类方法标记为def self
:
class UsingDefSelf
def self.a; 'private class method'; end
def self.b; 'private class method!'; end
private_class_method :a, :b
# In Ruby 2.1 there is an alternative syntax
private_class_method def self.c; 'private class method!'; end
end
但我们无法将其标记为protected
,没有protected_class_method
。 (但是,由于类是其singletonclass的唯一实例,私有类方法和受保护的类方法几乎相同,只是它们的调用语法不同。)
与使用class << self
标记private
类方法相比,它更容易,因为您必须在private_class_method
或前缀private_class_method
中列出所有方法名称到每个私有类方法定义。
答案 3 :(得分:5)
我认为他们认为self.*
更好,因为您可以肯定地说,它是一个类或实例方法,而无需向上滚动并搜索此class << self
字符串。
答案 4 :(得分:5)
无论你想要什么。两者都非常清楚你做了什么。但我想到了一些建议。
当只有一种类方法要定义时,使用def self.xxx
。因为仅定义一种方法,增加缩进级别可能会变得混乱。
如果要定义多个类方法,使用class << self
。因为撰写def self.xxx
,def self.yyy
和def self.zzz
肯定是重复的。为这些方法创建一个部分。
如果类中的所有方法都是类方法,则可以module
使用module_function
而不是class
。这使您可以使用def xxx
定义模块函数。
答案 5 :(得分:-2)
到目前为止,问题和答案仅讨论了这两个选项:
class MyClass
def self.method_name
..
end
end
class MyClass
class << self
def method_name
..
end
end
end
但是这里有另一个选择考虑类方法/单例方法/静态方法/方法在类级别上运行(或者你想要调用它们的任何其他方法):
class MyClass
def MyClass.method_name
..
end
end
我更喜欢这个选项,因为它的作用更明显。方法定义看起来就像在代码中调用它一样,很明显它在类级别上运行。
我也来自Python背景,其中self
用于实例方法,而在Ruby中,self
用于类方法。这经常让我感到困惑,所以要避免思考“Ruby中的自我方法是类还是实例方法?”我使用def ClassName.methodname
。