2009-08-11 18 views
30

Ruby de aprendizaje. Tengo la impresión de que los atributos booleanos deben ser nombrados de la siguiente manera:Ruby: convención de nomenclatura de atributos booleanos y uso

my_boolean_attribute? 

Sin embargo, consigo errores de sintaxis cuando se trata de hacer lo siguiente: "?"

class MyClass 
    attr_accessor :my_boolean_attribute? 

    def initialize 
    :my_boolean_attribute? = false 
    end 
end 

Al parecer, el rubí es odiar el . ¿Es esta la convención? ¿Qué estoy haciendo mal?

Respuesta

40

Edición: tres años después; los tiempos están cambiando ...

Julik's answer es la forma más sencilla y mejor manera de abordar el problema en estos días:

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

Mi respuesta a la pregunta original sigue, para la posteridad ...


la versión corta:

no puede utilizar un signo de interrogación en el nombre de una variable de instancia.

La versión más larga:

Tomemos, por ejemplo, attr_accessor :foo - es simplemente conceptualmente un poco de azúcar sintáctica para lo siguiente:

def foo 
    @foo 
end 

def foo=(newfoo) 
    @foo = newfoo 
end 

Por otra parte, el sufijo signo de interrogación es más que nada una convención para indicar que el valor de retorno de un método es un booleano.

La mejor aproximación que puedo hacer de lo que vamos a dar aquí ...

class MyClass 

    def initialize 
    @awesome = true 
    end 

    def awesome? 
    @awesome 
    end 

end 

En este caso, puede haber un caso que se hizo para el uso de attr_accessor - después de todo, puede ser explícita que estás trabajando directamente con un atributo booleano. En general, guardo el sufijo de interrogación para cuando estoy implementando un método cuyo valor de retorno booleano se basa en condiciones ligeramente más complejas que solo el valor de un atributo.

¡Salud!


Editar, dos años más tarde, después de una reciente comentario:

  1. Rubí hace cumplir ciertas convenciones de nomenclatura. Los símbolos en Ruby no pueden tener signos de interrogación. Por lo tanto, las invocaciones de :my_boolean_attribute? fallarán con un NameError. Editar: no es correcta, sólo tiene que utilizar la sintaxis citado para un símbolo, por ejemplo, :"my_attribute?"
  2. Los símbolos son inmutables, intentar asignar a uno lanzará una SyntaxError.
+6

Rubyist generalmente no usa el prefijo is_ ni en nombres de variables ni en nombres de métodos. ¿Simplemente impresionante? en lugar de is_awesome? –

+0

Buen punto, weppos. Editado el 'es_' para evitar la posteridad confusa ;-) –

+0

De esta respuesta me doy cuenta de que no hay una convención real? :/ –

5

? es una convención para nombres de métodos, no variables. No puede usar una variable de instancia llamada @foo?; sin embargo, puede usar una variable llamada @foo y nombrar el método getter (creado manualmente) foo? si lo desea.

+0

hmm, por lo que el attr_accessor ayudante no se desnudará el '?' fuera del final para mí eh. Me alegra escuchar que en realidad no es la convención, por ejemplo, vars también. Pensé que me estaba volviendo loco. –

6

El símbolo attr_accessor implica que el nombre de la variable es @my_boolean_attribute, por lo que es lo que debe establecer (no el símbolo).

Además, no puede usar? para variables, solo nombres de métodos.

+0

ty para la captura del símbolo. self.my_boolean_attribute funcionaría correctamente? –

+0

Sí, debería. –

+0

Ah, déjenme agregar-- solo dentro de los métodos de instancia. En el ámbito de clase, buscará una variable de ámbito de clases (@@ my_boolean_attribute). No es que tuviera que decírtelo, por supuesto, pero quería asegurarme de que lo que dije fuera técnicamente correcto. –

3

mono-parches metaprogramming - tal vez puede ser más elegante, este es sólo un borrador rápido, y no he hecho metaprogramming por un tiempo ...

# 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 este enfoque , puedes ser SECO y obtener el buen questionmark también. Es posible que necesite elegir un nombre mejor que "bool_attr", como "bool_attr_accessor" o algo similar.

Las definiciones que hice son un poco irritables, en el sentido de que el signo de interrogación está presente en el símbolo original. Probablemente, un enfoque más limpio sería evitar el signo de interrogación en el nombre del símbolo y anexarlo durante la definición del método; debería ser menos confuso.

Ah, y casi se olvidó de incluir el vínculo obligatorio: Seeing metaclasses clearly

+0

+1 para el enlace! Probablemente no agregará el método de conveniencia en este caso ya que no es la convención. No quiero confundir a los demás. ¡Sin embargo, las ideas serán felizmente canibalizadas por otros problemas! –

+1

Si lo mantiene en un equipo, creo que este tipo de preguntas deberían discutirse en profundidad en las revisiones; en algunos casos, podría tener sentido; en algunos casos, no. No codifiqué a Ruby en un equipo, así que tiendo a buscar un enfoque que me ofrezca el mínimo de LOC a quien mirar. –

+0

+1. Si solo fuera por el meta-ingenio ... –

38

La forma más fácil de añadir rápidamente un "método pregunta" es el uso de alias para el método lector

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

¡increíble! Lo estaba haciendo a mano. –

+0

Al usar esto, puede usar tanto 'dead' como' dead? ', ¿Verdad? Pero solo permite establecer a través de 'dead'? –

+3

El ajuste se mantiene en "muerto =" – Julik

Cuestiones relacionadas