2016-10-08 3 views
2

Пример 1:Различные способы создания метода класса в Ruby,

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, и почему? Существуют ли ситуации, когда предпочтение отдается другому?

+0

вы также можете написать 'def Dog.class_method; end', который вы также можете написать вне класса. –

ответ

3

this ruby style guide говорит, что синтаксис class << self «возможен и удобен, когда вам нужно определить многие методы класса».

У них есть примеры кода, использующие обе версии, поэтому определенно не существует широкого общественного согласия для использования одного над другим.

Я лично использую def self.my_method минимизировать отступ по

3

Вы просили различные способы создания методов класса. Вот некоторые.

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) доступны для использования в качестве (класса) методов всеми класами ses, поскольку классы являются экземплярами Class (H.class#=>Class).


class Object 
    def o 
    "O" 
    end 
end 

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

Это одна интересная. Object является предком Class (Class.ancestors #=> [Class, Module, Object, Kernel, BasicObject]), поэтому Class наследует метод экземпляра :o от Object. Следовательно (из предыдущего случая) :o - метод класса H. Однако H также является подклассом Object (H.superclass #=> Object), поэтому H наследует метод экземпляра Object#:o.


Что касается "наилучшего", это зависит. Если нужно создать несколько методов класса, большинство из них будет использовать A.Если понадобилось большое количество, я бы использовал D или B. Если методы класса должны были создаваться динамически, F или какой-либо вариант. Однако я не могу представить ситуацию, когда буду использовать G или H.