Yehuda Katz wrote an article about self
and metaclass . In the article he said that Person.instance_eval
assigns Person
's metaclass to self
for a class Person
. But this is obviously wrong.
class Person; end Person.instance_eval{ p self } #=> Person
As I mentioned in an old article , though I'm sorry about it is written in Japanese, Ruby always has three implicit contexts: self), so called klass' and the constant definition point.
Yehuda is confusing
self with
klass'.
self
self is the self
which you know.
It is the default receiver of method invocation.
There is always a self
.
p self # displays "main" class Foo def bar(a = (p self)) end end foo = Foo.new foo.bar # displays "#<Foo:0x471004>" class Foo class Baz < (p self; self) # displays "Foo" end end
On the top level, a special instance of Object
named "main" is the self.
Whenever you are, you can retrieve the self from the pseudovariable self
.
If you invoke a method without giving an explicit receiver, self
will receive the invocation.
so called `klass'
I called the conception `klass' in the old article but it might not be a good name. It is the default class onto which method is defined. Now I'd like to call it "default definee".
Ruby always holds the reference to a class as well as self
. But there is no way to retrieve it directly. It is more implicit than self
.
If you define a method without giving an explicit receiver, in other words, if you define a method with the normal method definition syntax, the default definee will have the method as an instance method.
Examples
On the top level, Object
is the class. So global functions are actually instance methods in Object
class as you know.
def hoge; end Kernel.instance_method(:hoge) #=> #<UnboundMethod: Object#hoge>
BTW, "hoge", "fuga", "piyo" is Japanese "foo", "bar", "baz".
class
syntax switches both self
and the default definee to the class which is now being defined.
class T def hoge; end end T.instance_method(:hoge) #=> #<UnboundMethod: T#hoge>
In a normal method body, self
is the receiver of the method invocation and the default definee is the syntactically outer class, now it is T
.
class T def hoge def fuga; end end end t = T.new t.hoge t.method(:fuga) #=> #<Method: T#fuga> T.instance_method(:fuga) #=> #<UnboundMethod: T#fuga>
Don't confuse it with def self.fuga
, an singleton method definition.
When you give a receiver to a method definition, the method will be adde into the eigenclass of the receiver.
class U def hoge def self.fuga; end end end u = U.new u.hoge u.method(:fuga) #=> #<Method: #<U:0x46dbf4>.fuga> U.instance_method(:fuga) # raises a NameError "undefined method `fuga' for class `U'"
U does not have an instance method named fuga
because fuga
is a singleton method of u
.
Wherever you are, there is a default definee. On evaluating a default value, the default definee is the outer class as well as in a method body.
class Bar; end $bar = Bar.new class Baz def $bar.hoge(a = (def fuga; end)) def piyo; end end end $bar.hoge Baz.instance_method(:fuga) #=> #<UnboundMethod: Baz#fuga> Baz.instance_method(:piyo) #=> #<UnboundMethod: Baz#piyo> $bar.method(:fuga) # raises a NameError "undefined method `fuga' for class `Bar'" $bar.method(:piyo) # raises a NameError "undefined method `piyo' for class `Bar'"
In other words, class
definition changes the default definee but method definition does not.
eval family
What instance_eval
does is
- changing
self
toinstance_eval
's receiver changing the default definee to the receiver's eigenclass.
- If the receiver does not have eigenclass yet, creating it.
evaluates the given block.
o = Object.new o.instance_eval do p self #=> #<Object:0x454f24> def hoge; end end o.method(:hoge) #=> #<Method: #<Object:0x454f24>.hoge> Object.instance_method(:hoge) # raises a NameError "undefined method `hoge' for class `Object'"
Let's go.
class T $o = Object.new $o.instance_eval do def hoge(a = (def fuga; end)) def piyo; end end end end $o.hoge $o.method(:fuga) #=> #<Method: #<Object:0x42d144>.fuga> $o.method(:piyo) #=> #<Method: #<Object:0x42d144>.piyo> T.instance_method(:fuga) # raises a NameError T.instance_method(:piyo) # raises a NameError
Because instance_eval
changes the default definee to the eigenclass of $o
, fuga
and piyo
will be singleton methods of $o
.
Oops, I should mention that
RUBY_VERSION #=> "1.9.1".
Ruby 1.8 acts more lexically, so you will contrarily get
$o.method(:fuga) # raises a NameError $o.method(:piyo) # raises a NameError T.instance_method(:fuga) #=> #<UnboundMethod: T#fuga> T.instance_method(:piyo) #=> #<UnboundMethod: T#piyo>
In Ruby 1.8, the default definee in the method body is based on the lexically outer class definition.
Anyway, in both Ruby 1.8 and 1.9, instance_eval
changes self
to the receiver, the default definee to its eigenclass.
Finally, class_eval
changes both self
and the default definee to the receiver.
self | default definee | |
---|---|---|
class_eval | the receiver | the receiver |
instance_eval | the receiver | eigenclass of the receiver |
In the my old article , I discussed about Kernel#eval
and instance_eval
/ class_eval
with String evaluation.
constant definition
When you use an instance variable, it is a instance variable of self
.
When you use an class variable, it is a class variable of self
's class; Or the one of self
itself when self
is a class.
But constants behave differently. It is another implicit context in Ruby. The ruby core team calls the conception "cref".
I must write a presentation for the comming RubyConf . So I'll discuss about cref later.