在 Ruby 中创建 Class 方法的不同方式

Different Ways of Creating Class Method in Ruby

示例 1:

class Dog
  def self.class_method
    :another_way_to_write_class_methods
  end
end

def test_you_can_use_self_instead_of_an_explicit_reference_to_dog
  assert_equal :another_way_to_write_class_methods, Dog.class_method
end

示例 2:

class Dog
  class << self
    def another_class_method
      :still_another_way
    end
  end
end

def test_heres_still_another_way_to_write_class_methods
  assert_equal :still_another_way, Dog.another_class_method
end

我可以知道在 Ruby 中首选哪种编写 class 方法的方式吗?为什么?是否存在一种情况优于另一种情况?

this ruby style guide 表示 class << self 语法是 "possible and convenient when you have to define many class methods."

他们有使用这两个版本的代码示例,因此对于使用其中一个版本肯定没有广泛的社区共识。

我个人使用def self.my_method来最小化缩进

您要求使用不同的方法来创建 class 方法。这里有一些。

class A
  def self.a
    "A"
  end
end
A.a #=> "A"

class B
  class << self
    def b
      "B"
    end
  end
end
B.b #=> "B"

class C
  singleton_class.class_eval do
    def c
      "C"
    end
  end
end
C.c #=> "C"

module M
  def m
    "M"
  end
end

class D
  extend M
end
D.m #=> "M"

class E
  class << self
    include M
  end
end
E.m #=> "M"

class F
  singleton_class.instance_eval do
    define_method(:f) do
      "F"
    end
  end
end
F.f #=> "F"

如果要动态创建:f

class F
end
F.singleton_class.instance_eval do
   define_method(:f) do
     "F"
   end
end

或变体:

F.singleton_class.instance_eval "define_method(:f) { 'F' }"
F.f #=> "F"

class Class
  def k
    "K"
  end
end

class G
end
G.k #=> "K"

这里的问题是 Class(包括 :k)的所有实例方法都可用作所有 classes 的(class)方法,因为classes 是 Class (H.class#=>Class) 的实例。


class Object
  def o
    "O"
  end
end

class H
end
H.o #=> "O"
H.new.o #=> "O"

这个很有趣。 ObjectClassClass.ancestors #=> [Class, Module, Object, Kernel, BasicObject])的祖先,所以Class继承了Object的实例方法:o。因此(从前面的例子来看),:oH 的 class 方法。但是,H也是Object的subclass(H.superclass #=> Object),所以H继承了实例方法Object#:o.


至于哪个是 "best",视情况而定。如果只创建几个 class 方法,大多数会使用 A。如果需要大量,我会使用 DB。如果要动态创建 class 方法,F 或某些变体。但是,我无法想象我会使用 GH.

的情况