69

这个Ruby 风格指南告诉你最好使用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

是否存在性能问题?

4

6 回答 6

101

class << self擅长将所有类方法保存在同一个块中。如果方法是以def self.method形式添加的,则不能保证(除了约定和一厢情愿)文件中稍后不会有额外的类方法。

def self.method擅长明确说明方法是类方法,而class << self你必须自己去寻找容器。

其中哪一个对您更重要是一个主观决定,并且还取决于有多少其他人正在处理代码以及他们的偏好是什么。

于 2012-06-09T20:04:15.320 回答
31

通常,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因为可能会有更多人理解它。除非您希望您的听众理解它,否则无需引入元语法。

于 2012-06-09T20:35:42.407 回答
28

如上所述,两种样式似乎是等效的,但是使用class << self允许将类方法标记为privateprotected。例如:

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只影响实例方法。使用单例类,我们定义了该类的实例方法,这些实例方法变成了包含类的类方法!

我们还可以将类方法标记privatedef 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。(但是,由于类是其单例类的唯一实例,因此私有类方法和受保护类方法几乎相同,只是它们的调用语法不同。)

而且它比使用class << self标记类方法更容易,因为您必须在每个私有类方法定义private中列出所有方法名称private_class_method或前缀。private_class_method

于 2015-01-09T18:09:21.907 回答
6

随便你。两者都非常清楚您的工作。但我对此提出了一些建议。

当只有一个类方法要定义时, Use def self.xxx。因为只定义一种方法,增加缩进级别可能会变得混乱。

当有多个类方法要定义时, Use class << self。因为写作def self.xxxdef self.yyy而且def self.zzz肯定是重复。为这些方法创建一个部分。

当一个类中的所有方法都是类方法时,可以使用modulewithmodule_function代替class。这让您可以定义模块函数,只需使用def xxx.

于 2012-06-09T23:14:39.923 回答
5

我认为他们认为self.*更好,因为您可以肯定地说,它是一个类或实例方法,而无需向上滚动并搜索此class << self字符串。

于 2012-06-09T19:58:00.083 回答
-3

到目前为止,问题和答案只讨论了这两个选项:

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

它不流行并且更冗长,但它是最明确的选项。

如果您将selfPython 和 Ruby 之间的行为混为一谈,也不会那么混乱。

于 2015-01-16T09:42:25.317 回答