liveBook · Manning

Private member

As explained in The Well-Grounded Rubyist, Fourth Edition

A private instance method is an instance method whose invocation cannot use an explicit receiver other than self.

A baker can accept a request to bake a cake without accepting separate requests to crack an egg or stir batter. Ruby’s private instance methods make that distinction: an object can use these methods to do its work, while callers cannot invoke them with an explicit receiver other than self. Instance methods are public unless their access level is changed. section 5.3 section 5.3.1 section 5.4.1

Listing 5.8 Baker and other baking-domain classes
class Cake
  def initialize(batter)
    @batter = batter
    @baked = true
  end
end
class Egg
end
class Flour
end
class Baker
  def bake_cake
    @batter = []      #1
    pour_flour
    add_egg
    stir_batter
    return Cake.new(@batter)      #2
  end
  private                        1
  def pour_flour
    @batter.push(Flour.new)       #3
  end
  def add_egg
    @batter.push(Egg.new)
  end
  def stir_batter
  end
end

Follow bake_cake: it calls pour_flour, add_egg, and stir_batter without receivers. The private declaration makes the methods defined below it private; bake_cake remains public. section 5.3.1

Calling b.add_egg fails because b is an explicit receiver. Inside a Baker instance method, bare add_egg works: Ruby sends a call without an explicit receiver to the current object, self. An explicit self.add_egg also works. The distinction is about the receiver written at the call site, not whether the method has a receiving object. section 5.3.1 section 5.4.1

Two ways to declare private methods are:

  • Place private before method definitions. Subsequent instance methods are private until another access declaration, such as public or protected, changes the setting. section 5.3.1
  • Name methods explicitly, as in private :pour_flour, :add_egg, :stir_batter. section 5.3.1

A private setter

A setter needs special care. In an age= method that updates a private dog_years= method, write self.dog_years = years * 7. Without self, the assignment is to a local variable rather than a call to the setter. This is the usual exception to the preference for bare private-method calls. section 5.3.1 section 5.4.1

A method defined at the top level can likewise be called as a bareword from elsewhere: it is available as a private instance method through the Object and Kernel method-lookup path, not as a public method on an arbitrary object. To inspect an object’s private method names, call private_methods; a method you declare private appears in that list. section 5.4.1 section 5.5 section 15.2.2

Privacy also matters when invoking methods by name. send can call a private method, whereas public_send cannot. If a method name comes from user input, check or restrict the allowed names rather than passing the input unchecked to send. section 2.3.3

How The Well-Grounded Rubyist, Fourth Edition covers it

How deep it goes
Explains declarations, receiver rules, setter exceptions, top-level availability, and introspection without descending into runtime implementation.
Examples
Uses a baker’s internal tasks, a private setter, top-level talk calls, and private-method inspection.
What it assumes
Assumes familiarity with classes and instance methods while explaining the default receiver and private-call rules.
What you can do after
Build it from scratch by declaring private helpers and calling them through self while recognizing where explicit receivers fail.
How it connects
Connects private methods to self, public and protected access, method lookup, setters, and dynamic dispatch.

Also explained in

Compare how 12 books explain private member →

Related concepts

This explainer was generated by Manning's knowledge graph from the text of The Well-Grounded Rubyist, Fourth Edition. The section links point to the parts of the book it draws on.