2009-08-11 7 views
30

Ruby di apprendimento. Sono sotto l'impressione che gli attributi booleani devono essere chiamati come segue:Ruby: convenzione di denominazione degli attributi booleani e utilizzo

my_boolean_attribute? 

Tuttavia, ottengo errori di sintassi quando si tenta di effettuare le seguenti operazioni: "?"

class MyClass 
    attr_accessor :my_boolean_attribute? 

    def initialize 
    :my_boolean_attribute? = false 
    end 
end 

Apparentemente Ruby è odiare il . E 'questa la convenzione? Che cosa sto facendo di sbagliato?

risposta

40

Modifica: tre anni dopo; i tempi, che sono a-changin' ...

Julik's answer è il modo più semplice e migliore per affrontare il problema in questi giorni:

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

La mia risposta alla domanda iniziale segue, per i posteri ...


la versione corta:

non è possibile utilizzare un punto di domanda in nome di una variabile di istanza.

La versione più lunga:

Prendiamo, per esempio, attr_accessor :foo - è semplicemente concettualmente un po 'di zucchero sintattico per i seguenti:

def foo 
    @foo 
end 

def foo=(newfoo) 
    @foo = newfoo 
end 

Inoltre, il suffisso punto interrogativo è per lo più solo una convenzione per indicare che il valore di ritorno di un metodo è un valore booleano.

la migliore approssimazione che posso fare di ciò che si sta andando per qui ...

class MyClass 

    def initialize 
    @awesome = true 
    end 

    def awesome? 
    @awesome 
    end 

end 

In questo caso, ci può essere un caso da effettuare per l'utilizzo di attr_accessor - dopo tutto, può essere esplicita che stai lavorando direttamente con un attributo booleano. Generalmente, salvi il suffisso del punto interrogativo per quando sto implementando un metodo il cui valore di ritorno booleano è basato su condizioni leggermente più complesse del solo valore di un attributo.

Cheers!


Modifica, due anni più tardi, dopo un recente commento:

  1. Rubino fa rispettare certe convenzioni di denominazione. I simboli in Ruby non possono avere punti interrogativi. Così invocazioni di :my_boolean_attribute? falliranno con uno NameError. Edit: non è corretto, basta usare la sintassi citato per un simbolo, per esempio, :"my_attribute?"
  2. simboli sono immutabili, il tentativo di assegnare ad uno lancerà un SyntaxError.
+6

Rubyist di solito non usa il prefisso is_ né nei nomi delle variabili né nei nomi dei metodi. Semplicemente fantastico? invece di is_awesome? –

+0

Buon punto, weppos. Modificato il 'is_' per evitare di confondere i posteri ;-) –

+0

Da questa risposta deduco che non c'è una vera convenzione? :/ –

5

? è convenzione per i metodi, non per le variabili. Non è possibile utilizzare una variabile di istanza denominata @foo?, tuttavia è possibile utilizzare una variabile denominata @foo e denominare il metodo getter (creato manualmente) foo? se si desidera.

+0

hmm, in modo che l'attr_accessor l'aiutante non toglierà il "?" alla fine per me huh. Sono contento di sentire che in realtà non è nemmeno la convenzione, ad esempio vars. Pensavo che stavo impazzendo. –

6

Il simbolo attr_accessor implica che il nome della variabile sia @my_boolean_attribute, quindi è quello che dovresti impostare (non il simbolo).

Inoltre, non è possibile utilizzare? per le variabili, solo i nomi dei metodi.

+0

ty per il simbolo. self.my_boolean_attribute funzionerebbe correttamente? –

+0

Sì, dovrebbe. –

+0

Oh, lasciami aggiungere-- solo all'interno dei metodi di istanza. Nell'ambito della classe cercherà una variabile scope class (@@ my_boolean_attribute). Non che avessi bisogno di dirtelo, certo, ma volevo assicurarmi che quello che dicevo fosse tecnicamente corretto. –

3

scimmia-patching metaprogrammazione - forse può essere reso più elegante, questo è solo un rapido progetto, e non ho fatto metaprogrammazione per un po '...

# 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? 

Con questo approccio , puoi essere ASCIUTTO e ottenere anche il bel punto interrogativo. Potrebbe essere necessario selezionare un nome migliore di "bool_attr", ad esempio "bool_attr_accessor" o qualcosa di simile.

Le definizioni che ho creato sono un po 'irritabili, nel senso che il punto interrogativo è presente nel simbolo originale. Probabilmente un approccio più pulito sarebbe evitare il punto interrogativo nel nome del simbolo e aggiungerlo durante la definizione del metodo - dovrebbe essere meno confuso.

Oh, e quasi dimenticato di includere il link obbligatorio: Seeing metaclasses clearly

+0

+1 per il collegamento! Probabilmente non aggiungerà il metodo di convenienza in questo caso poiché non è la convenzione. Non voglio confondere gli altri. Le idee saranno fortunatamente cannibalizzate da altri problemi però! –

+1

Se lo stai mantenendo in una squadra, immagino che questo tipo di domande dovrebbe essere discusso approfonditamente alle recensioni - in alcuni scenari potrebbe avere senso, in alcuni scenari non lo sarà. Non ho codificato Ruby in una squadra, quindi tendo ad avere un approccio che mi dà il minimo LOC a cui guardare. –

+0

+1. Se solo per la meta-intelligenza ... –

38

Il modo più semplice per aggiungere rapidamente un "metodo domanda" è quello di utilizzare l'aliasing per il metodo lettore

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

fantastico! Lo stavo facendo a mano lunga. –

+0

Usando questo puoi usare sia 'dead' che' dead? ', Giusto? Ma consente solo l'impostazione tramite 'dead'? –

+3

L'impostazione rimane attraverso "dead =" – Julik