2009-08-11 163 views
30

学习ruby。我的印象就是那个如下布尔属性应该被命名为:Ruby:布尔属性命名约定和使用

my_boolean_attribute? 

但是,试图做到以下几点,当我得到语法错误:“?”

class MyClass 
    attr_accessor :my_boolean_attribute? 

    def initialize 
    :my_boolean_attribute? = false 
    end 
end 

显然红宝石仇富。这是惯例吗?我究竟做错了什么?

回答

40

编辑:三年后;时代,他们是 - 起了变化...

Julik's answer为解决这个问题,这些天最简单,最好的方法:

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

我的回答原来的问题如下,供后人......


简短版本:

您不能在实例变量的名称中使用问号。

较长的版本:

举个例子来说,attr_accessor :foo - 这是只是概念以下一点语法糖:

def foo 
    @foo 
end 

def foo=(newfoo) 
    @foo = newfoo 
end 

此外,问号后缀大多是刚一个表示方法的返回值是布尔值的约定。

最佳逼近我可以让你要什么,这里的......

class MyClass 

    def initialize 
    @awesome = true 
    end 

    def awesome? 
    @awesome 
    end 

end 

在这种情况下,有可能的情况下为使用attr_accessor进行 - 毕竟,这可能是明文规定你直接使用布尔属性。通常,当我实现一个方法,其布尔型返回值基于稍微复杂的条件而不仅仅是属性的值时,我保存问号后缀。

干杯!


编辑,两年后,最近的评论后:

  1. 红宝石强制执行特定的命名约定。 Ruby中的符号不​​能有问号。因此,:my_boolean_attribute?的调用都将失败,并显示NameError编辑:不正确,只需使用引号语法表示符号,例如:"my_attribute?"
  2. 符号是不可变的,试图分配给一个将会抛出一个SyntaxError
+6

Rubyist通常不会在变量名称或方法名称中使用is_前缀。真棒吗?而不是is_awesome? – 2009-08-11 22:23:48

+0

好点,weppos。编辑'is_'以避免混淆后人;-) – 2009-08-11 22:25:41

+0

从这个答案我收集有没有一个真正的约定? :/ – 2011-04-27 22:17:29

5

?是方法名称的约定,而不是变量。您不能使用名为@foo?的实例变量,但是您可以使用名为@foo的变量,并根据需要命名(手动创建的)获取方法foo?

+0

嗯,所以attr_accessor中帮手不会去掉'?'为我而告终。很高兴听到它实际上不是公约的例子。以为我疯了。 – 2009-08-11 22:08:37

6

attr_accessor符号意味着变量名称是@my_boolean_attribute,所以这就是你应该设置的(不是符号)。

另外,你不能使用?对于变量,只是方法名称。

+0

ty为符号捕获。 self.my_boolean_attribute会正常工作吗? – 2009-08-11 22:10:16

+0

是的,它应该。 – 2009-08-12 14:14:09

+0

哦,让我加 - 只在实例方法中。在类作用域中,它将查找一个类作用域变量(@@ my_boolean_attribute)。当然,我不需要告诉你,但我想确保我所说的技术上是正确的。 – 2009-08-12 18:49:14

3

猴补丁元编程 - 也许它可以变得更优雅,这仅仅是一个快速的草案,我没有做过元编程了一小会儿......

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

用这种方法,你可以干,并获得好的问号。您可能需要选择比“bool_attr”更好的名称,例如“bool_attr_accessor”或类似的名称。

我所做的定义有点胡思乱想,因为问号出现在原始符号中。可能更清晰的方法是避免符号名称中的问号,并在方法的定义过程中追加它 - 应该不那么令人困惑。

哦,差点忘了,包括强制性的链接:Seeing metaclasses clearly

+0

+1链接!这种情况下可能不会添加便利方法,因为它不符合约定。我不想混淆别人。虽然这些想法会被其他问题愉快地蚕食掉! – 2009-08-11 22:38:20

+1

如果你在一个团队中维护它,我想这种问题应该在评论中进行深入讨论 - 在某些情况下它可能是有意义的,在某些情况下它不会。我没有在一个团队中编写Ruby代码,所以我倾向于采取一种让我至少注意LOC的方法。 – 2009-08-11 23:00:14

+0

+1。如果只为元智慧... – 2009-08-12 15:59:04

38

快速添加一个“问题的方法”的最简单方法是使用别名为你的读者的方法

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

真棒!我一直在做这件事。 – 2009-08-13 15:25:11

+0

通过使用这个,你可以同时使用'dead'和'dead?',对吗?但只允许通过“死”设置? – 2011-04-27 22:19:32

+3

设置保持通过“死=” – Julik 2012-06-30 22:51:11