Dan Rubio Dan Rubio - 5 months ago 9
Ruby Question

Can someone help explain the post_initialize callback for class creation (Sandi Metz)

I am reading Sandi Metz's POODR and have come across a coding principle that I don't quite understand. Here is the code:

class Bicycle
attr_reader :size, :chain, :tire_size

def initialize(args = {})
@size = args[:size] || 1
@chain = args[:chain] || 2
@tire_size = args[:tire_size] || 3
post_initialize(args)
end
end

class MountainBike < Bicycle
attr_reader :front_shock, :rear_shock

def post_initialize(args)
@front_shock = args[:front_shock]
@rear_shock = args[:rear_shock]
end
end

mb = MountainBike.new(front_shock: 4, rear_shock: 5)
puts mb.size
puts mb.chain
puts mb.tire_size
puts mb.front_shock
puts mb.rear_shock


This code will output
1,2,3,4,5
for its respective attributes. What I don't understand is the method look up.

When a mountain bike is instantiated, because it does not have its own
initialize
method, it will travel up the method lookup chain onto its super class (
Bicycle
). But now from there, it seems that Bicycle then moves back down into MountainBike's post_initialize method. Instead of continuing up the method chain, how can it go back down? Is
post_initialize
a ruby keyword like
initialize
in that it serves some sort of special function? Is there some other ruby introspection methods I can use to see what is going on?

Answer

The important thing to understand here is that in this code:

def initialize(args = {})
  # ...
  post_initialize(args)
end

...post_initialize has an implicit receiver, self. In other words, post_initialize(args) here is equivalent to self.post_initialize(args), and self is an instance of MountainBike. Method lookup always starts with the receiver's class, so it has no trouble finding MountainBike#post_initialize.

 That's a lie; it's not equivalent when it comes to privacy; private methods cannot be called with an explicit receiver.
 That's also a lie; it actually starts with the receiver's singleton class, but then it tries its class.

Comments