If you’re new to ruby, then you may be tempted to implement private class methods like this:
class MachineBuilder
def self.build_printer
build(:printer)
end
def self.build_laser
build(:laser)
end
private
def self.build(:machine_type)
parts = get_parts(:machine_type)
machine = assemble(parts)
machine
end
def self.get_parts(:machine_type)
# fancy logic here
end
def self.assemble(parts)
# more fancy logic here
end
end
In this example, we have a MachineBuilder
that exposes two class
methods, build_printer
and build_laser
. These methods delegate their
work to other methods. Our intent is to expose a minimal interface to
anyone using MachineBuilder
, so we want to hide how it actually
builds printers and lasers.
We try using the private
keyword to change the visibility of our
“internal” methods, build
, get_parts
and assemble
. This does not
work. These three methods are still publicly visible.
Why Is This Approach Broken?
The keyword private
, is a
method.
It sets the visibility for “subsequent methods” to private. The method
applies to instance methods, not class methods.
Alternative Implementations
class MachineBuilder
def self.build_printer
build(:printer)
end
def self.build_laser
build(:laser)
end
def self.build(:machine_type)
parts = get_parts(:machine_type)
machine = assemble(parts)
machine
end
def self.get_parts(:machine_type)
# fancy logic here
end
def self.assemble(parts)
# more fancy logic here
end
private_class_method :build, :get_parts, :assemble
end
This implementation works by adding class methods and then
using the private_class_method
from Module
to declare
the desired methods as private.
class MachineBuilder
def self.build_printer
build(:printer)
end
def self.build_laser
build(:laser)
end
class << self
private
def build(:machine_type)
parts = get_parts(:machine_type)
machine = assemble(parts)
machine
end
def get_parts(:machine_type)
# fancy logic here
end
def assemble(parts)
# more fancy logic here
end
end
end
This alternative implementation works by adding private instance methods to
MachineBuilder
’s eigenclass (a.k.a. singleton or meta class).
The difference between instance and class methods will be covered in a different post.