日々徒然

プログラミングしたりお酒飲んだりする毎日

Rubyの特異クラス内のインスタンス変数について

はじめに

Ruby Goldのお勉強中によく分からない挙動をしていたので手元で動かしてみた。

特異クラス内のインスタンス変数

まずはこのコード

class A
  @a = 1
  def call_a
    p @a
  end

  class << self
    @a = 2
    def call_a
      p @a
    end
  end
end

Aクラスの中でインスタンス変数@aに1を代入&特異クラス内で@aに2を代入

メソッドを呼んでみる

A.new.call_a => nil

A.call_a => 1

A.new.call_anilになるのは分かる(initializeインスタンス変数に値がセットされてない)けど、A.call_aで2じゃなくて1になるのがよく分からなかった...

けど、手を動かしてみるとなるほどなという結果

class << selfの中でselfを呼んでみる

class A
  @a = 1
  def call_a
    puts @a
  end

  class << self
    @a = 2
    p self # => #<Class:A>
    def call_a
      puts @a
    end
  end
end

#<Class:A>Aクラスの特異クラス。

つまり@aは特異クラス内のインスタンス変数ということなので、特異クラス内に特異クラスを作りレシーバーを特異クラスにしてメソッドを定義すれば取ってこれる(何言ってるか謎)

class A
  @a = 1
  def call_a
    puts @a
  end

  class << self
    @a = 2
    def call_a
      puts @a
    end

    class << self
      def call_a_from_singleton_class
        puts @a
      end
    end
  end
end

A.singleton_class.call_a_from_singleton_class # => 2

singleton_classは自身の特異クラスを返すので、それをレシーバーにしてもう一つネストの深い特異クラスのスコープの中でメソッドを定義する。

まとめ

そもそも特異クラスのスコープの中にインスタンス変数を定義するのかどうか分からない。

自分は見たことがない。

まぁまたちょっとRubyに詳しくなったのでヨシ✋