1. Technology
You can opt-out at any time. Please refer to our privacy policy for contact information.

Method Visibility

By

Method Visibility

The concept of 'encapsulation' is at the core of Object Oriented programming. Object Oriented programming is grouping related data and methods into a coherent class, as well as providing an interface for that class. The user of these objects and classes use the interface and don't touch the internal state of the object, this is often referred to as 'encapsulation.' Ruby provides both a way to prevent unwanted instance variable accesses, as well as unwanted method invocation by defining three method visibilities.

Public Method Visibility

The default method visibility is public. If a method is public, anyone can call it. It can be called from another instance method as well as from outside of the class. Public methods are methods as everyone knows them, methods without restrictions on how and when they can be called.

Private Method Visibility

There are many reasons you would not want a method to be called from outside of the class. Many classes often have methods that modify the internal state of an object without sufficient integrity checks, and these should be hidden from the user to maintain encapsulation. Further, non-API methods (small utility methods not useful outside of the class, for example) can be made private to communicate to the programmer that that method is uninteresting and to not try to use it.

Private instance methods are only callable from instance methods not only of the same class, but of the same object. To reiterate, private methods are only callable if the self value in both callee and caller will be the same. It isn't enough if the caller is an instance method of the same class, it must be executing in the context of the same object.

In addition, private methods are only callable with implicit receiver. A private method can never be called with the dot notation, it must always be called from an instance method as a "naked" method call. You can't even use self.some_private_method. Even if that should be OK, it won't work.

Private methods are the main way to implement this type of method hiding in Ruby. In order to make any method private, simply call the Module#private method from within a module or class definition. All methods defined after that will be defined as private methods. Alternatively, the private method can take any number of symbol arguments. This variant does not change the default visibility of the defined methods, but it will change the visibility of the methods referred to by the symbol arguments.


class Test
  def a_public_method
    # This will succeed
    a_private_method

    # This will fail
    self.a_private_method
  end

private
  def a_private_method
    puts "Hello from a private method"
  end
end

Protected Methods

Protected methods are similar to private methods, but with some of the restrictions relaxed. Protected methods can be called from anywhere where the self value is the same as the receiver (even using explicit receivers) or from anywhere where the caller's self is of the same type of the callee's self.


class Test
  def do_test(m)
    m.spin
  end

protected
  def spin
    puts "Wheee!"
  end
end

t1 = Test.new
t2 = Test.new

t2.do_test(t1)

Listing Methods by Visibility

On any class or instance, you can call the methods method to get a list of methods. However, this returns a list of all methods. This is typically done from IRB to see how an object is used, so do we really need to see private methods? In order to see only methods with the desired, use the methods public_methods or public_instance_methods.

Visibility is not Security

It's easy to think of visibility as a type of security. That you can lock the internal state of your objects away and that it can't be accessed because private methods are barring the way. This just isn't true. Private methods exist to separate interface from function. There's nothing really stopping a user from accessing private methods, should they really want to.

One trick to access private methods seems like magic at first, but once you know the criteria for calling public and private methods, it's not magic at all. Say if you have the following class, and you wish to call the update_state method from outside the class. One way to do this is to use the send method.


class Test
  attr_reader :state

  def initialize(state)
    @state = state
  end

  private
  def update_state(s)
    @state = state
  end
end

t = Test.new(:before)

# This will raise an exception
t.update_state(:after)

# This will not
t.send(:update_state, :after)

Why did the second method call using send not raise an exception? Any method can be called if the caller and callee's self value are the same. Since you're not actually calling the update_state method from outside the object (it's being called by the send method), it gets around the restriction.

Ruby is a totally open language. There are many tricks to get to the internal state of any object should a programmer so desire. So do your best to separate state from interface and trust the user won't do anything they're not supposed to. Though it's very rarely necessary to monkey around with the internal state of an object to fix a bug or work around a limitation without having to re-engineer anything.

  1. About.com
  2. Technology
  3. Ruby
  4. Beginning Ruby
  5. Object Oriented Programming
  6. Method Visibility

©2014 About.com. All rights reserved.