LoginSignup
56
51

More than 5 years have passed since last update.

カレントオブジェクトselfについて Ruby

Last updated at Posted at 2014-04-13

Rubyのプログラムの実行は常にオブジェクトをかいして行われていて、メソッドが呼び出されるとレシーバはselfになる。カレントオブジェクトはカレントクラスのインスタンスである。

下記のコードを見てほしい。

> [1,2,3].map(&:even?)

=> [false, true, false]

以下のコードを打った時にこのオブジェクトのレシーバはArrayのクラスのインスタンスであるがselfに着目して言えばレシーバであるオブジェクトがカレントオブジェクトであり、カレントクラスのインスタンスである。

selfはRubyプログラムのなかに同時に複数存在しない。

クラス定義のメソッド定義の中で実行してみる


class Cat

  def where_self
    self
  end
end

Cat.new.where_self

=> #<Cat:0x007f8c03205440>

Catクラスのインスタンスが返ってくる。

名前空間で実行してみる


module Zoo
  class Cat
    def where_self
      self
    end
  end
end
Zoo::Cat.new.where_self

=> #<Zoo::Cat:0x007f8c02bf4f10>

Zoo::Catクラスのインスタンスが返ってくる。

interactive ruby、略してirbで実行してみる

> self
=> main

mainというオブジェクトが返ってきた、これはどういう意味か?
mainのクラスを調べてみれば分かる。

> self.class
=> Object

mainはObjectのインスタンスであるようだ、
irbはオブジェクトの内部がmainに属していてそこでメソッド等が実行されているようだ。

クラスメソッドを定義する時にselfにドットをつけて定義していた。


class Cat
  def self.class_method
    "class_method"
  end
end

newなどのクラスメソッドを使ってインスタンス化してオブジェクトを生成するがクラス自身もオブジェクトになれて、
このselfはクラス名を指していてクラス定義にselfが使われるときはクラス名を指す。

これを知っておくとインスタンス変数とクラスインスタンス変数を区別できるようになる。

selfはオブジェクトを指すがクラス定義ではクラス名を指し以下のコードに着目して欲しい。


class Cat
  @siro = "kuro"
  attr_reader :siro

  def initialize(siro="siro")
    @siro = siro
  end

  def self.kuro
    @siro
  end
end

a = Cat.new
a.siro
=> "siro"
Cat.siro
=> "kuro"

同じ@siroのインスタンス変数だが違う値が入っている。
aオブジェクトがselfとなるインスタンス変数かCatがselfとなるインスタンス変数がある、後者をクラスインスタンス変数という。

selfへの理解があればeval属性のinstance_evalやclass_evalなどの理解にも役に立つ。

instance_evalとは?

selfに変更を加えることができるメソッド


class Cat
  def initialize(cat="siro")
    @cat = cat
  end

  def value
    @cat
  end
end

a = Cat.new
a.value
# => "siro"

a.instance_eval do 
  @cat = "kuro"
end

a.value
# => "kuro"

オブジェクトはクラスの参照とインスタンス変数をもつ、本来であればクラス定義でattr_accessorとかメソッドを定義して値の有無を制御するがこのメソッドを使えばオブジェクトのカプセル化を壊せる。
上の例ではオジェクトがもつインスタンス変数に"kuro"という値を格納している。

class_evalとは?

selfに変更を加えることでき、なおかつ、カレントクラスをオープンしてクラス定義の外からクラスに変更を加えることができる


class Cat
  def kuro
    "kuro"
  end
end

Cat.class_eval do
  def siro
    "siro" 
  end
end

a = Cat.new
a.siro
# => "siro"

クラスを内部からではなく、外部からクラスのメソッドを定義する。

まとめ

カレントオブジェクトのselfは現在のオブジェクトを指し、同時に複数存在できない。

カレントオブジェクトの所属するクラスをカレントクラスという。

instance_evalを使えばselfに変更を加えることができる

class_evalを使えばselfとカレントクラスに変更を加えることができる

続く、、、、

56
51
1

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
56
51