2012-04-15 22 views
4

Rubyには、クラスメソッドを宣言するいくつかの方法があります。我々は、これら2つの形式がありなぜ "class << self"式を使用するのですか?

...

class Dog 

    def self.species 
    puts "I'm a dog." 
    end 

    def Dog.species_rly? 
    puts "Still a dog." 
    end 

end 

そしてこの他、長い形...

class Dog 
    class << self 
    def species_srsly? 
     puts "OK, fine. I'm a cat." 
    end 
    end 
end 

は、なぜ最後の形式が使用されていますか?これを行うよりもどのように優れていますか?

class Dog 
    def Dog.some_method 
    # ... 
    end 
end 
+2

'Dog.species'は後でクラス名を変更すると問題があります。 'self.species'を使いましょう。 –

答えて

1

class << selfは、少なくとも繰り返しです。 def Dog.methは、クラス全体で「Dog」を繰り返し、def self.methは「self」を繰り返します。

余分な字下げは、あなたのシングルトンのishクラスのメソッドであり、通常のインスタンス化されたメソッドではないことを示す視覚的インジケータでもあります。

2

class << selfフォームは、少数のメソッドを処理する場合にのみ長くなります。あなたが15のクラスのメソッドを書こうとしているのなら、それは突然よりはっきりしていて、繰り返しの回数は少なくなります。

1日の終わりに、それはあなたが使用する重要な、または個人的なスタイルです。

1

違いは全くなく、最終的には優先事項です。後者は、すべての「クラス」メソッドを1つのブロックにまとめ、各メソッド定義にself.を書く必要がないためです。

前者は、各メソッドが各定義で明示的な「クラス」メソッドであるという事実を作り出します。

リファクタリングがself.some_methodより難しくなるため、Dog.some_methodを使用するとは思いません。

3

This wonderful bookは、3つの構文が同一であることを示します。どちらを選択するかは、個人的な好みの問題です。また、クラス名の構文(def Dog.some_method)はRubyコミュニティにぶち壊されているとも言われています。そして私は理由を知ることができます:あなたは理由なしに情報を複製しています。あなたのクラスの名前を変更する場合は、すべてのメソッド定義も更新する必要があります。

だから、あなたは残りの2つの構文の間で自由に選択できます:)

1

技術に差は(少なくとも私は何も知らない)はありません。私は、クラス名を変更する場合

私は

class Dog 
    def Dog.species_rly? 
    puts "Still a dog." 
    end 
end 

を避けるため、私は、各メソッドの定義では、それを変更する必要があります。 同じですが、あるクラスから別のクラスにメソッドをコピーした場合(そうした場合は、モジュールを定義してそのクラスをインクルードする必要があると思います)。私は1つのまたは2つのメソッドを持っている場合

は、私が使用します。私はより多くのクラスメソッドを持っている場合は

class Dog 

    def self.species 
    puts "I'm a dog." 
    end 

end 

、その後、私は最初の理由だと思います。 クラスメソッドはしばしば、悪いデザインのヒントです - おそらく別の(シングルトン?)クラスが必要です。

私は、私が使用する複数のクラスメソッドを定義することを決定した場合:

class Dog 
    class << self 
    def species_srsly? 
     puts "OK, fine. I'm a cat." 
    end 
    end 
end 

時々私はsourcefileの中にクラスメソッドを分離し、別のソースファイル名でインスタンスメソッドを置きます。

0

Dogクラスでは、selfは 'Dog'クラスです(すべてのクラスには 'class'オブジェクトがあり、メタクラスまたはeigenclassと呼ばれることもあります)。

ruby​​のすべてのメソッドは、インスタンスメソッドです。

def self.species 

は、「クラスクラス」で種別メソッドを宣言しています(クラスメソッドと同じように動作します)。同様

d = Dog.new 
def d.bark; puts "woof"; end 

class << self 
    def species 

def self.species 

それらが機能的に目を達成するとの間の差については 'D' インスタンス

にメソッドを追加します同じこと。もう1つのフォーマットを選択すると、他のタイプのフォーマットと同じように、書式が選択されます。 def self.speciesは、 'class'メソッドを宣言するための通常のものです。

私はむしろインスタンスよりも、クラスレベルで動作する属性のアクセサを作りたいとしたら、私はほとんど

class << self 
    attr_accessor :species 
end 

を使用します。樹皮方法:これはモジュールのようなフックを使用することが重要である理解

はまた

module Sound 
    def self.included(host_class) 
    def host_class.speak(sound) 
     define_method(:bark) do 
     sound 
     end 
    end 
    end 
end 
class Dog 
    include Sound 
    speak "woof" 
end 
Dog.new.bark 

を含め、完全

class Dog 
    def self.species 
    puts self.to_s 
    end 
    def Dog.bark 
    puts self.to_s 
    end 
end 
class Spaniel < Dog; end 

のための種の方法は、一方で、任意のサブクラスの自己上で定義されています(上書きされない限り)常に犬に定義されます