class MyClass
def mymethod
MYCONSTANT = "blah"
end
end
给我错误:
SyntaxError:动态常量分配错误
为什么将其视为动态常数?我只是给它分配一个字符串。
class MyClass
def mymethod
MYCONSTANT = "blah"
end
end
给我错误:
SyntaxError:动态常量分配错误
为什么将其视为动态常数?我只是给它分配一个字符串。
Answers:
您的问题是,每次运行该方法时,您都将为常量分配一个新值。这是不允许的,因为它会使常数变得非常数。即使字符串的内容是相同的(暂时而言),每次调用该方法时,实际的字符串对象本身也有所不同。例如:
def foo
p "bar".object_id
end
foo #=> 15779172
foo #=> 15779112
也许,如果您解释了用例(为什么要在方法中更改常量的值),我们可以帮助您实现更好的实现。
也许您宁愿在类上有一个实例变量?
class MyClass
class << self
attr_accessor :my_constant
end
def my_method
self.class.my_constant = "blah"
end
end
p MyClass.my_constant #=> nil
MyClass.new.my_method
p MyClass.my_constant #=> "blah"
如果您确实想在方法中更改常量的值,并且您的常量是String或Array,则可以“作弊”并使用该#replace
方法使对象采用新值,而无需实际更改对象:
class MyClass
BAR = "blah"
def cheat(new_bar)
BAR.replace new_bar
end
end
p MyClass::BAR #=> "blah"
MyClass.new.cheat "whee"
p MyClass::BAR #=> "whee"
def initialize(db,user,password) DB=Sequel.connect("postgres://#{user}:#{password}@localhost/#{db}") end
。这是Ruby没有简单方法的情况之一。
@variable
),而不是常量。否则,DB
每次实例化该类的新实例时,您都将重新分配。
Sequel.connect
名为DB的常量。实际上,文档明确指出,这只是一个建议。这听起来不像是我的外部约束。
因为Ruby中的常量不是要更改的,所以Ruby不鼓励您在可能多次执行的代码部分(例如内部方法)中分配给它们。
通常情况下,您应该在类本身内定义常量:
class MyClass
MY_CONSTANT = "foo"
end
MyClass::MY_CONSTANT #=> "foo"
如果由于某种原因确实需要在方法内部定义常量(也许用于某种元编程),则可以使用const_set
:
class MyClass
def my_method
self.class.const_set(:MY_CONSTANT, "foo")
end
end
MyClass::MY_CONSTANT
#=> NameError: uninitialized constant MyClass::MY_CONSTANT
MyClass.new.my_method
MyClass::MY_CONSTANT #=> "foo"
同样,const_set
在正常情况下,您并不是真正必须求助的东西。如果不确定是否真的要以这种方式分配给常量,则可以考虑以下替代方法之一:
类变量在许多方面表现得像常量。它们是类的属性,可以在定义它们的类的子类中访问。
区别在于类变量是可修改的,因此可以毫无问题地分配给内部方法。
class MyClass
def self.my_class_variable
@@my_class_variable
end
def my_method
@@my_class_variable = "foo"
end
end
class SubClass < MyClass
end
MyClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass
SubClass.my_class_variable
#=> NameError: uninitialized class variable @@my_class_variable in MyClass
MyClass.new.my_method
MyClass.my_class_variable #=> "foo"
SubClass.my_class_variable #=> "foo"
类属性是一种“类上的实例变量”。它们的行为有点像类变量,只是它们的值不与子类共享。
class MyClass
class << self
attr_accessor :my_class_attribute
end
def my_method
self.class.my_class_attribute = "blah"
end
end
class SubClass < MyClass
end
MyClass.my_class_attribute #=> nil
SubClass.my_class_attribute #=> nil
MyClass.new.my_method
MyClass.my_class_attribute #=> "blah"
SubClass.my_class_attribute #=> nil
SubClass.new.my_method
SubClass.my_class_attribute #=> "blah"
只是为了完整性,我应该提到:如果您需要分配一个只能在实例化类之后才能确定的值,那么您很有可能实际上正在寻找一个普通的旧实例变量。
class MyClass
attr_accessor :instance_variable
def my_method
@instance_variable = "blah"
end
end
my_object = MyClass.new
my_object.instance_variable #=> nil
my_object.my_method
my_object.instance_variable #=> "blah"
MyClass.new.instance_variable #=> nil
在Ruby中,任何名称以大写字母开头的变量都是常量,您只能分配一次。选择以下替代方法之一:
class MyClass
MYCONSTANT = "blah"
def mymethod
MYCONSTANT
end
end
class MyClass
def mymethod
my_constant = "blah"
end
end
红宝石中的常量不能在方法内部定义。例如,请参阅本页底部的注释
非常感谢Dorian和Phrogz提醒我有关数组(和哈希)方法#replace的知识,该方法可以“替换数组或哈希的内容”。
常量值可以更改,但带有恼人的警告的观念,是Ruby少数概念上的失误之一-这些失误应该是完全不变的,或者是完全抛弃了不变的想法。从编码者的角度来看,常数是声明性的和有意的,这是对其他人的信号,即“一旦声明/分配,此值实际上是不可更改的”。
但是有时“明显的声明”实际上会排除其他未来有用的机会。例如...
在某些合法的用例中,可能确实需要更改“常数”的值:例如,从类似于REPL的提示循环中重新加载ARGV,然后通过更多(后续)OptionParser.parse重新运行ARGV!电话-瞧!为“命令行参数”提供了一个全新的动态实用程序。
实际问题是,无论是与推定假设,即“ARGV必须是一个常量”,或在optparse自己的初始化方法,其中硬编码ARGV的分配给实例VAR @default_argv进行后续处理-即阵列(ARGV)真应该作为一个参数,在适当的情况下鼓励重新解析和重用。适当的参数化以及适当的默认值(例如ARGV)将避免需要更改“恒定” ARGV。仅有价值2美分的想法...