The code below outputs "I am Thing."
class Thing
class << self
def foo
puts "I am #{self}."
end
end
end
Thing.foo
I thought "self" refers to an object of type Thing, but it refers to the class Thing. I have gathered from a previous question (linked in the comments) that this has something to do with the fact that Thing is an instance of Object. Is the block beginning with class << self actually executed in a context where "self" refers to Thing as an instance? What is going on here?
Inside methods self
refers to the instance, inside class/module definition, but outside of any method — to the class/module itself.
class Thing
puts self.inspect
def foo
puts self.inspect
end
end
puts "==="
Thing.new.foo
Try the code above and you’ll likely see what’s happening there: the class is being parsed in the first place, and the first puts
is being executed. Then puts "==="
prints the "==="
string out. And, afterwards, the instance is being printed from inside the method.
Let's find out.
class Thing
puts "self=#{self}"
class << self
puts "self in singleton class=#{self}"
def foo
puts "I am #{self}."
end
end
end
# self=Thing
# self in singleton class=#<Class:Thing>
and
Thing.foo
# I am Thing.
We see class << self
is the same as class << Thing
.
This is the same as
class Thing
end
class << Thing
puts "self in singleton class=#{self}"
def foo
puts "I am #{self}."
end
end
# self in singleton class=#<Class:Thing>
Thing.foo
# I am Thing.
class << self
within the class or class << Thing
outside the class does one thing and one thing only: it changes self
to Thing
's singleton class within the block that follows. That is the same as saying that it changes the scope to Thing
's singleton class within the block.
This article by Yehuda Katz is required reading.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With