4

Ruby では、クラス メソッドを宣言する方法がいくつかあります。

この2つの形があります...

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
4

6 に答える 6

3

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

したがって、残りの 2 つの構文から自由に選択できます :)

于 2012-04-15T21:20:11.953 に答える
2

class << self少数のメソッドを扱っている場合にのみ、フォームが長くなることがわかります。たとえば、15 個のクラス メソッドを記述しようとすると、突然、より明確になり、繰り返しが少なくなります。

結局のところ、それはあなたが使用する問題または個人的なスタイルです.

于 2012-04-15T21:19:38.203 に答える
1

class << self繰り返しが最も少ないです。def Dog.methクラス全体で「犬」をdef self.meth繰り返し、「自分」を繰り返します。

余分なインデントは、通常のインスタンス化されたメソッドではなく、シングルトンっぽいクラス メソッドにいることを視覚的に示している可能性もあります。

于 2012-04-15T21:44:56.947 に答える
1

絶対に違いはなく、最終的には好みの問題です。すべての「クラス」メソッドを単一のブロックにまとめ、self.各メソッド定義に書き込む必要がなくなるため、後者を好む人もいます。

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

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

于 2012-04-15T21:19:51.980 に答える
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

時々、ソース ファイル内のクラス メソッドを分離し、インスタンス メソッドを別のソース ファイルに配置します。

于 2012-04-15T21:23:18.253 に答える
0

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

難しいことに、Ruby のメソッドはすべてインスタンス メソッドです。

def self.species

「クラスクラス」で種メソッドを宣言しているため、クラスメソッドのように動作します。

同様に、

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

「d」インスタンスにメソッドを追加します

の違いについては、

class << self
  def species

def self.species

それらは機能的に同じことを達成します。他の人で述べたように、ある形式を他の形式よりも選択することは、文体的です。def self.species は、「クラス」メソッドを宣言するための通常のものです。

私は主に使用します

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

種メソッドはサブクラスの自己で定義されますが、:bark メソッドは常に Dog で定義されます (上書きされない限り)。

于 2012-04-16T12:43:38.737 に答える