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とカレントクラスに変更を加えることができる