Ruby の初心者向け記事にときどき,クラスが定数であるかのような記述が見られます。
これは,
class Hoge
end
p defined? Hoge # => "constant"
というところから来ているのでしょうね。
defined?
のあとに定数名を書くと "constant"
という文字列を返す仕様ですが,そのとおりになっているので,Hoge
が定数であることが分かります。
でね,上の例で
-
Hoge
はクラスである -
Hoge
は定数である
はまあ正しいんだけれども,
- クラスは定数である
と言っちゃうとおかしなことになります。
だって,クラスは一つのオブジェクトだし,定数はオブジェクトを指すものでしょ。
では正確にはどういうことなのか?
こうです。
class Hoge
end
というクラス定義式を実行すると,「Hoge
」という名前のクラスが定義され,それが同名の定数に代入された状態になる,ということなんです。
だから Hoge
はクラス名であり,それを指す定数の名でもあるわけです。
決してクラス自体が定数というわけではありません。
class Hoge
end
# クラスの名前を表示
p Hoge.name # => "Hoge"
# クラスを定義したことで同名の定数が Object に定義されたことを確認
p Object.constants.include?(:Hoge) # => true
では無名のクラスを定義するとどうなるのでしょうか。
Class.new
で名前の無いクラスが作れます。
c = Class.new
# (1) 名前を持たないことを確認
p c.name # => nil
# (2) なんかの定数に代入
Hoge = c
# (3) 名前が出来た!
p c.name # => "Hoge"
# (4) 別の定数にも代入
Fuga = c
# (5) 名前は変わらない
p c.name # => "Hoge"
名前を持たないクラスの名前を求めると((3) のところ),自身が代入されている定数を探し,見つかればその定数名を自身の名前とします。
名前が出来るのは (2) の時点ではなく (3) の時点です。
(4) で別の定数に代入していますが,既にクラスは名前を持っているので,(5) では (4) の影響を受けていません。
なお,初めて名前を求めたときに複数の定数に代入されている場合,いずれの定数の名前がクラス名に採られるかは不定だそうです。
参考:Class.new (Ruby 3.0.0 リファレンスマニュアル)