【问题标题】:Different Ways of Creating Class Method in Ruby在 Ruby 中创建类方法的不同方法
【发布时间】:2017-02-17 14:45:00
【问题描述】:

示例 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 中首选哪种编写类方法的方式,为什么?是否存在优先于另一个的情况?

【问题讨论】:

  • 你也可以写def Dog.class_method;end,你也可以写在类块之外。

标签: ruby class methods syntax class-method


【解决方案1】:

this ruby style guide 表示class &lt;&lt; self 语法“在您必须定义许多类方法时可能且方便。”

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

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

【讨论】:

    【解决方案2】:

    您要求创建类方法的不同方法。这里有一些。

    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)的所有实例方法都可以被所有类用作(类)方法,因为类是ClassH.class#=&gt;Class)的实例。


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

    这个很有趣。 ObjectClass (Class.ancestors #=&gt; [Class, Module, Object, Kernel, BasicObject]) 的祖先,所以ClassObject 继承实例方法:o。因此(从前一个案例),:oH 的类方法。但是H也是ObjectH.superclass #=&gt; Object)的子类,所以H继承了实例方法Object#:o


    至于哪个是“最好的”,这取决于。如果只创建几个类方法,大多数会使用A。如果需要大量,我会使用DB。如果要动态创建类方法,F 或一些变体。但是,我无法想象我会使用GH 的情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2013-11-17
      • 2019-10-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-09-19
      相关资源
      最近更新 更多