Rubyプログラムでの作業インスタンス変数からクラス変数への状態データの移動を探していましたが、インスタンス変数は自動化されていますが、初期化せずに読み込もうとすると自動的にnil
に初期化されています)、クラス変数はありません。これは私にとって非常に矛盾しています(Rubyのほとんどの構文は非常に一貫しています)。Rubyのクラス変数は自動化されていませんか?
サンプルプログラム:@id
が初期化されなかった場合
class Test
def id
@id.to_i
end
def id=(i)
@id = i
end
def nextid
self.id = id + 1
end
end
t = Test.new
puts t.nextid #=> 1
puts t.nextid #=> 2
その場合、Test::id
を呼び出すには、Rubyが(その後、私は0を得るためにそれをto_i
)nil
にそれを自動vivifyます。
今、私は私が実行しているIDがTest
インスタンス間で共有されたくないので、私はこのようにそれを書き換えることを決定:
class Test
def id
@@id.to_i
end
def id=(i)
@@id = i
end
def nextid
self.id = id + 1
end
end
t = Test.new
puts t.nextid
puts t.nextid
同じように機能するなら、私は思ったが、何も:
NameError: uninitialized class variable @@id in Test
しかし、この回避策が動作します(!?):
class Test
def id
(@@id ||= 0).to_i
end
def id=(i)
@@id = i
end
def nextid
self.id = id + 1
end
end
t = Test.new
puts t.nextid #=> 1
puts t.nextid #=> 2
(0に怠惰な初期化を行った後、付与されましたto_i
を削除できますが、一貫性のために残しました)。
Rubyは「遅延初期化」を理解し、魔法がNameError
を投げていないために、必要に応じてそれを扱うように見えます - ||=
はおそらくx = x || val
にだけ糖衣構文であるにも関わらず(ところで、クラス変数をINITINGを求めるためのおかげで動作しません)。
どうしてですか?
'X || = val'は、x 'とちょっと同じです|| x = x ||ではなく、x = val'でなければなりません。 val'。また、あなたのコードでは、なぜインスタンスメソッドがクラス変数を設定したいのですか? –
あなたはどのRubyバージョンをテストしていますか?私はruby-2.2で2番目のケースを試しました。2、私はNoMethodError:未定義のメソッド '+'を返します。これは 'NameError:初期化されていないクラス変数@@ id'の代わりにnil:NilClass'です。 – fangxing
@fangxing:Rubyのバージョンに依存しないと思います。私はそれが質問のタイプミスだと言いたい。 'self.id = id + 1'を使って、上記のエラーを得ることができます。 –