2012-04-15 20 views
4

In Ruby gibt es mehrere Möglichkeiten, eine Klassenmethode zu deklarieren.Warum verwenden wir den Ausdruck "class << self"?

Wir haben diese beiden Formen ...

class Dog 

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

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

end 

Und die andere, längere Form ...

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

Warum ist die letzte Form verwendet? Wie ist es besser als nur das zu tun?

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

'Hund.species' ist problematisch, wenn Sie den Klassennamen später ändern. Verwenden Sie besser "self.species". –

Antwort

1

class << self ist die am wenigsten wiederholende. def Dog.meth wiederholt "Dog" in der gesamten Klasse und def self.meth wiederholt "self".

Die zusätzliche Einrückung kann auch ein visueller Hinweis darauf sein, dass Sie sich in Ihren Singleton-Klassenmethoden und nicht in Ihren normalen instanziierten Methoden befinden.

2

Sie werden feststellen, dass die class << self Form nur mehr, wenn Sie mit einer kleinen Anzahl von Methoden zu tun hat. Wenn Sie beispielsweise 15 Klassenmethoden schreiben, ist es plötzlich viel klarer und viel weniger repetitiv.

Am Ende des Tages ist es eine Sache oder ein persönlicher Stil, den Sie verwenden.

1

Es gibt absolut keinen Unterschied, und es ist letztlich eine Frage der Präferenz. Einige mögen letzteres, weil es alle "Klassen" -Methoden in einen einzigen Block bringt und es vermeidet, self. in jede Methodendefinition schreiben zu müssen.

Die erste macht die Tatsache, dass jede Methode eine "Klasse" -Methode in jeder Definition explizit ist.

Ich glaube nicht, dass ich jemals die Dog.some_method verwenden würde, da es das Refactoring schwieriger macht als self.some_method.

3

This wonderful book sagt, dass die drei Syntaxen identisch sind. Welches zu wählen ist eine Frage der persönlichen Präferenz. Es besagt auch, dass die Klassennamensyntax (def Dog.some_method) in der Ruby-Community verpönt ist. Und ich kann verstehen warum: Du vervielfältigst Informationen ohne Grund. Wenn Sie Ihre Klasse umbenennen, müssen Sie auch alle Methodendefinitionen aktualisieren.

Sie sind also frei zwischen den verbleibenden zwei Syntaxen wählen :)

1

Technische gibt es keinen Unterschied (zumindest ich keine kennen).

Ich vermeide

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

Wenn ich die Klassennamen zu ändern, muß ich es in jeder Methodendefinition ändern. Gleiches, wenn ich eine Methode von einer in eine andere Klasse kopiere (wenn du das tust, denke zuerst darüber nach, ob du ein Modul definieren und es einfügen sollst).

Wenn ich ein oder zwei Methoden habe ich verwenden:

class Dog 

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

end 

Wenn ich mehr Klassenmethoden haben, dann zuerst denke ich, warum. Klassenmethoden sind oft nur ein Hinweis auf schlechtes Design - vielleicht brauchen Sie eine andere (Singleton?) Klasse.

Wenn ich entscheiden, mehrere Klassenmethoden zu definieren, die ich benutze:

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

Manchmal trenne ich die Klassenmethoden in einem Quell und setzen Sie die Instanz-Methoden in einem anderen Quell.

0

In der Klasse Dog ist self die 'Dog'-Klasse (jede Klasse hat ein' class'-Objekt, manchmal auch eine Meta-Klasse oder Eigenklasse genannt).

In einer kniffligen Weise sind alle Methoden in Ruby Instanzmethoden.

def self.species 

deklariert eine Spezies-Methode auf der 'Klassen-Klasse', die es (verhält sich) wie eine Klassenmethode macht.

Ähnlich

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

fügt eine Methode, um die 'D' Instanz

Was den Unterschied zwischen

class << self 
    def species 

und

def self.species 

sie funktionell voll th Das Gleiche. Die Auswahl eines Formats gegenüber dem anderen, wie in anderen erwähnt, ist stilistisch. def.Species ist die übliche Methode, um Klassenmethoden zu deklarieren.

meist würde ich

class << self 
    attr_accessor :species 
end 

verwenden, wenn ich ein Attribut Accessor auf der Ebene der Klassen arbeiten zu wollen, war zu machen, anstatt Instanz.

Verständnis dieser zu verwenden Haken wichtig ist wie das Modul

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 

Ebenfalls enthalten, der Vollständigkeit halber

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

Die Art Verfahren basiert auf der Selbst von allen Unterklassen definiert, während der: Rinden Verfahren ist immer auf Hund definiert (wenn nicht überschrieben)

Verwandte Themen