Instance Methods, self, and to_s
Prerequisites: Accessors
Inside an instance method, self refers to the object the method
was called on. Most of the time you don't need to write it — Ruby
assumes it — but it's there when you need it.
class Temperature
attr_reader :celsius
def initialize(celsius)
@celsius = celsius
end
def fahrenheit
celsius * 9.0 / 5 + 32 # same as self.celsius
end
def hotter_than?(other)
celsius > other.celsius
end
def to_s
"#{celsius}°C"
end
end
today = Temperature.new(24)
yesterday = Temperature.new(19)
puts today.fahrenheit
puts today.hotter_than?(yesterday)
puts today
puts "Today it's #{today}"
p today.celsius
75.2
true
24°C
Today it's 24°C
24
celsiusinsidefahrenheitcalls the reader on the current object (self).hotter_than?(other)compares this object with another one of the same class.- Defining
to_scontrols how the object looks when printed withputsor placed in interpolation. Without it, Ruby prints something like#<Temperature:0x000... @celsius=24>.
inspect is to_s's developer-facing sibling — it's what p and
irb show. Ruby's default inspect lists the instance variables,
which is usually fine.
Method chaining with self
Returning self from a method lets callers chain calls:
class Order
attr_reader :items
def initialize
@items = []
end
def add(item)
@items << item
self
end
end
order = Order.new.add("tea").add("cake")
p order.items
["tea", "cake"]
Common mistakes
- Overriding
to_sto return something other than a string.putsthen shows the default object description instead.
Practice
Give the Temperature class a to_s that shows both scales, like
24°C / 75.2°F.
Show solution
class Temperature
attr_reader :celsius
def initialize(celsius)
@celsius = celsius
end
def fahrenheit = celsius * 9.0 / 5 + 32
def to_s = "#{celsius}°C / #{fahrenheit}°F"
end
puts Temperature.new(24)