回答:
問題は、メソッドを実行するたびに新しい値を定数に割り当てていることです。定数を非定数にするため、これは許可されません。文字列の内容は同じですが(今のところ、とりあえず)、メソッドが呼び出されるたびに実際の文字列オブジェクト自体は異なります。例えば:
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"
メソッド内の定数の値を本当に変更したい場合で、定数が文字列または配列である場合は、「チート」して#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が単純な方法を持たないケースの1つです。
@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では、名前が大文字で始まる変数は定数であり、1回しか割り当てることができません。次のいずれかの方法を選択してください:
class MyClass
MYCONSTANT = "blah"
def mymethod
MYCONSTANT
end
end
class MyClass
def mymethod
my_constant = "blah"
end
end
ルビの定数はメソッド内で定義できません。たとえば、このページの下部にあるメモを参照してください
「配列またはハッシュの内容を置き換える」ことができる配列(およびハッシュ)メソッド#replaceについて思い出してくれたDorianとPhrogzに感謝します。
CONSTANTの値は変更できるが、迷惑な警告が表示されるという概念は、Rubyのいくつかの概念的なミスステップの1つです。これらは完全に不変であるか、または一定のアイデアを完全にダンプする必要があります。コーダーの観点から見ると、定数は宣言的で意図的なものであり、「この値は、宣言または割り当てられた後は、実際には変更できない」というシグナルです。
しかし、「明白な宣言」が他の将来の有用な機会を実際に排除することもあります。例えば...
「定数」の値を実際に変更する必要がある正当なユースケースがあります。たとえば、REPLのようなプロンプトループからARGVを再ロードしてから、さらに(後続の)OptionParser.parseを介してARGVを再実行します。コール-出来上がり!「コマンドライン引数」にまったく新しい動的ユーティリティを提供します。
実用上の問題は、いずれかの「ARGVは一定でなければならない」という推定仮定して、またはその後の処理のインスタンスのvar @default_argvにどのハードコード、optparseは自身の初期化方法でARGVの割り当て-その配列(ARGV)本当に必要に応じて、再解析と再利用を促進するパラメーターにする必要があります。適切なデフォルト(たとえば、ARGV)を使用した適切なパラメーター化により、「定数」ARGVを変更する必要がなくなります。ちょうど2¢相当の考え...