LoginSignup
0
0

クラス、インスタンス、無名クラスの見分け方

Last updated at Posted at 2023-08-19

クラス、インスタンス、無名クラスの違いについて少しハマったのでメモ

例えばあるクラスのサブクラスを全て取得したい時は以下のコードで取得できる

class Hoge
    def self.subclasses
        ObjectSpace.each_object(Class).select { |klass| klass < self && klass.name != "" }
    end
end

ここであるクラスが自分のクラスを継承していることを表す条件式が klass < self なのだが、このクラスの継承に関する演算子 < はインスタンスとクラスで呼び出すとエラーになる

class Fuga < Hoge
end

p Fuga < Hoge # true

fuga = Fuga.new
p fuga < Hoge # Error

最初の subclass method でなぜエラーにならないかというとそれは each_object(Class) の部分でインスタンスが除外されているからだ

ObjectSpace.each_object(klass) は指定された klassObject#kind_of? の関係にある全てのオブジェクトに対して繰り返す、とある(参考

実際にインスタンスに対して kind_of?(Class) を呼び出してみると

p fuga.kind_of?(Class) # false

Class クラスとは関連がないと判定される

一方で無名クラスというものがあって、これは Class.new で作成される名前のないクラスなのだが、これは Class クラスと関連があると判定される

foo = Class.new(Fuga)
p foo.kind_of?(Class) # true

無名クラスの紛らわしいところは、オブジェクトを p コマンドなどで出力するとあたかもインスタンスのようなメモリの番地が表示された出力になることだ

p fuga # #<Fuga:0x0000000126a2cc00>
p foo # #<Class:0x0000000126a3f260>

しかし実際には fuga はインスタンスで foo はクラスである
出力で見分けようと思ったら先頭の #<Class: をみて判断するしかない

じゃあClass クラスのインスタンスはどうなるのかと思ったら、こちらは無名クラスと同じ扱いらしい

bar = Class.new
p bar # #<Class:0x000000012686b240>
p bar.kind_of?(Class) # true

確実に見分けようと思ったら kind_of?(Class) を呼ぶしかなさそうだ

結論

インスタンスと無名クラスは紛らわしいので注意
確かめたかったら kind_of?(Class) を呼んでみれば良い

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0