2009-08-11 13 views
30

Lernen Rubin. Ich habe den Eindruck, dass boolean Attribute wie folgt benannt werden:Ruby: Namenskonvention für Boolesche Attribute und Verwendung

my_boolean_attribute? 

Aber ich Syntaxfehler erhalten, wenn versucht wird, Folgendes zu tun: „?“

class MyClass 
    attr_accessor :my_boolean_attribute? 

    def initialize 
    :my_boolean_attribute? = false 
    end 
end 

Offenbar Rubin haßt die . Ist das die Konvention? Was mache ich falsch?

Antwort

40

Edit: drei Jahre später; die Zeiten, sie sind a-changin' ...

Julik's answer die einfachste und beste Weg ist, um das Problem in diesen Tagen zu bewältigen:

class Foo 
    attr_accessor :dead 
    alias_method :dead?, :dead # will pick up the reader method 
end 

Meine Antwort auf die ursprüngliche Frage folgt, für die Nachwelt ...


die kurze Version:

Sie können nicht ein Fragezeichen im Namen einer Instanzvariablen verwenden.

Die längere Version:

Nehmen wir zum Beispiel, attr_accessor :foo - es ist einfach konzeptionell ein bisschen syntaktischer Zucker für die folgenden:

def foo 
    @foo 
end 

def foo=(newfoo) 
    @foo = newfoo 
end 

Darüber hinaus ist die Fragezeichen Suffix ist meist nur Eine Konvention, die angibt, dass der Rückgabewert einer Methode ein boolescher Wert ist.

Die beste Annäherung ich machen kann, was Sie hier gehen ...

class MyClass 

    def initialize 
    @awesome = true 
    end 

    def awesome? 
    @awesome 
    end 

end 

In diesem Fall kann ein Fall sein für die Verwendung von attr_accessor gemacht werden - schließlich kann es ausdrücklich, dass Sie arbeiten direkt mit einem booleschen Attribut. Im Allgemeinen speichere ich das Fragezeichensuffix für die Implementierung einer Methode, deren boolescher Rückgabewert auf etwas komplexeren Bedingungen als nur dem Wert eines Attributs basiert.

Prost!


bearbeiten, zwei Jahre später, nach einer letzten Bemerkung:

  1. Rubin erzwingt bestimmte Namenskonventionen. Symbole in Ruby können keine Fragezeichen haben. Somit werden Aufrufe von :my_boolean_attribute? beide mit einem NameError fehlschlagen. Edit: nicht korrekt, verwenden Sie einfach die in Anführungszeichen gesetzte Syntax für ein Symbol, z. B. :"my_attribute?"
  2. Symbole sind unveränderlich, versucht, eine zu zuweisen, wird eine SyntaxError werfen.
+6

Normalerweise verwendet Rubyist weder in Variablennamen noch in Methodennamen das Präfix is_. Einfach super? statt is_awesome? –

+0

Guter Punkt, wirppos. Editiert das 'is_', um die Nachwelt zu verwirren ;-) –

+0

Von dieser Antwort kann ich sagen, dass es keine echte Konvention gibt? :/ –

5

? ist Konvention für Methodennamen, keine Variablen. Sie können keine Instanzvariable mit dem Namen @foo? verwenden. Sie können jedoch eine Variable mit dem Namen @foo verwenden und die (manuell erstellte) Getter-Methode foo? benennen, wenn Sie dies möchten.

+0

hmm, so die attr_accessor Der Helfer wird das "?" Ende für mich, huh. Freut mich zu hören, dass es tatsächlich nicht die Konvention zum Beispiel vars auch ist. Dachte, ich würde verrückt werden. –

6

Das attr_accessor Symbol bedeutet, dass der Variablenname @my_boolean_attribute ist, also sollten Sie das einstellen (nicht das Symbol).

Sie können auch nicht verwenden? Für Variablen nur Methodennamen.

+0

ty für den Symbolfang. self.my_boolean_attribute würde funktionieren? –

+0

Ja, sollte es. –

+0

Oh, lass mich hinzufügen - nur innerhalb der Instanz Methoden. Im Klassenbereich wird nach einer Klassenbereichsvariablen gesucht (@@ my_boolean_attribute). Nicht, dass ich es dir sagen müsste, aber ich wollte sichergehen, dass das, was ich gesagt habe, technisch korrekt war. –

3

Monkey-Patching metaprogramming - vielleicht kann es eleganter gemacht werden, dass dies nur ein kurzer Entwurf ist, und ich habe nicht Metaprogrammierung für eine kleine Weile getan ...

# inject the convenience method into the definition of the Object class 
class Object 
    def Object::bool_attr(attrname) 
    class_eval { define_method(attrname.to_s, 
      lambda { instance_variable_get('@' + attrname.to_s.chop) }) } 
    class_eval { define_method(attrname.to_s.chop+"=", 
      lambda { |x| instance_variable_set('@'+attrname.to_s.chop, x) }) } 
    end 
end 

### somewhere later 

class MyClass 

    bool_attr :my_boolean_attribute? 

    def initialize 
    @my_boolean_attribute = true 
    end 
end 

# yet even more later 

foo = MyClass.new 
bar = MyClass.new 

foo.my_boolean_attribute = 1 
puts foo.my_boolean_attribute? 
puts bar.my_boolean_attribute? 

Mit diesem Ansatz Du kannst DRY sein und auch das schöne Fragezeichen bekommen. Sie müssen nur einen besseren Namen als "bool_attr", wie "bool_attr_accessor" oder etwas Ähnliches auswählen.

Die Definitionen, die ich gemacht habe, sind ein bisschen verschroben, in einem Sinne, dass das Fragezeichen im ursprünglichen Symbol vorhanden ist. Wahrscheinlich wäre ein sauberer Ansatz, das Fragezeichen im Symbolnamen zu vermeiden und es bei der Definition der Methode anzuhängen - sollte weniger verwirrend sein.

Oh, und fast vergessen den obligatorischen Link zu enthalten: Seeing metaclasses clearly

+0

+1 für den Link! Wahrscheinlich wird in diesem Fall die Bequemlichkeitsmethode nicht hinzugefügt, da es nicht die Konvention ist. Ich möchte andere nicht verwirren. Die Ideen werden aber glücklicherweise von anderen Problemen ausgeschlachtet! –

+1

Wenn Sie es in einem Team pflegen, denke ich, dass diese Art von Fragen in Besprechungen ausführlich diskutiert werden sollte - in einigen Szenarien kann es Sinn machen, in einigen Szenarien wird es nicht. Ich habe Ruby nicht in einem Team programmiert, also tendiere ich zu einem Ansatz, der mir den geringsten LOC gibt, auf den ich starren kann. –

+0

+1. Wenn nur für die Meta-Cleverness ... –

38

Der einfachste Weg, um schnell eine „Frage-Methode“ hinzuzufügen ist Aliasing für Ihre Leser-Methode verwenden

class Foo 
    attr_accessor :dead 
    alias_method :dead?, :dead # will pick up the reader method 
end 
+0

genial! Ich habe es lange gemacht. –

+0

Mit diesem können Sie sowohl "tot" als auch "tot" verwenden, oder? Aber erlaubt nur Einstellung durch "tot"? –

+3

Einstellung bleibt durch "dead =" – Julik

Verwandte Themen