###結論
定数の定義される場所は、定義された時のネスティングによって決まる。
class_eval
でクラスを開いてその中に定数を定義した際、意図した場所に定数が定義されていないことから、定数はどこに定義されるのか疑問が湧きました。
class MyClass; end
MyClass.class_eval do
CONST = "Fuga"
end
上記のように定数を定義すると、初心者の私はMyClass::CONST
に定義されていそう!と思いました。
が、実際には、、、
pry(main)> MyClass::CONST
#=> NameError: uninitialized constant MyClass::CONST
pry(main)> CONST
#=> "Fuga"
???Ruby何一つわからない…となってしまったのですが、定数の定義場所はネスティングによって決まるということを教えてもらい、謎が解けました。
以下、順を追って説明します。
###ネスティングとは
ネスティングとは、すごくざっくり言ってしまうと"構文的な構造上のコードの区分"で(厳密な定義と間違っていたらごめんなさい)、
class識別子を使用したクラスの定義とmodule識別子を使用したモジュール定義によって切り替わり、Module.nesting
によって確認できます。
class MyClass
p Module.nesting
end
#=> [MyClass]
このネスティングに対応する位置に定数は定義されています。
CONST_TOP = "Foo"
pry(main)> p Module.nesting
#=> []
# ネスティングがトップレベルだと空
module A
CONST_A = "Bar"
p Module.nesting
#=> [A] ネスティングが切り替わる
class B
CONST_B = "Hoge"
p Module.nesting
#=> [A::B, A] ネスティングが切り替わる
end
end
pry(main)> CONST_TOP
#=> "Foo"
pry(main)> A::CONST_A
#=> "Bar"
pry(main)> A::B::CONST_B
#=> "Hoge"
#ネスティングに対応した位置に定数が定義されている!
それでは、先ほどの例に戻りclass_eval
でクラスを開いて定数を定義してみると、その定数はどこに定義されるのでしょうか?
class MyClass; end
MyClass.class_eval do
p Module.nesting
#=> [] ネスティングは切り替わっておらず、トップレベルのまま!
CONST = "Fuga"
end
# class_evalのブロックの中に入ってもネスティングは切り替わっておらず、トップレベルのまま。
# ということは、定数CONSTはトップレベルのネスティングの位置に定義されているはず!
pry(main)> CONST
#=> "Fuga"
# なるほど〜
MyClass::CONST
に定数が定義されているのでは?と思ってしまうのは、class_eval
を使うとコンテキストがMyClassに切り替わっているためなんですね…
MyClass.class_eval do
p self
#=> MyClass
# コンテキストがMyClassに切り替わるため(selfがMyClassに切り替わるため)、
# 見た目的にMyClass::定数名の位置に定数が定義されていると勘違いしてしまった…
end
###まとめ
定数の定義場所はネスティングによって決まる(コンテキストは関係無い)ため、定数を定義する際はネスティングに注意しよう!という話でした。