class<<自我与自我方法与Ruby:什么更好?

时间:2012-06-09 19:48:32

标签: ruby

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

是否存在性能问题?

6 个答案:

答案 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可以将类方法标记为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仅影响实例方法。使用单例类,我们定义该类的实例方法,它们转换为包含类的类方法!

我们还可以使用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.xxxdef self.yyydef 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