Access Control in Ruby classes
When designing a Ruby class, users of the class should rely on the details of the class’ implementation rather than its internal logical interface. One way to enforce this is by restricting the amount of access to a Ruby class’ methods.
Ruby has three levels of access control:
-
Public methods: can be invoked by anyone. Methods are public by default except for initialize.
-
Protected methods: can be invoked by objects of the defining class and its subclasses. Access is kept within the family.
-
Private methods: cannot be called with an explicit receiver. The receiver is the current object, self. Therefore, private methods can only be invoked in the context of the current object and with self or with the implicit receiver.
The following class MyClass
demonstrates usage:
class MyClass
def method1
# this method is public by default
end
protected
# subsequent methods will be "protected"
def method2
# this method is protected
end
private
# subsequent methods will be private
def method3
# this method is private
end
public
# subsequent methods will be "public"
def method4
# this method is public
end
end
Let’s take a look at the following example. For example, we want an accounting system where every debit also has a credit. To make sure no one can violate this rule, we can make the debit
and credit
methods private and design our interface to only expose the transfer
method publicly.
class Account
attr_accessor :balance
def initialize(balance)
@balance = balance
end
end
class Transaction
def initialize(account_a, account_b)
@account_a = account_a
@account_b = account_b
end
def transfer(amount)
debit(@account_a, amount)
credit(@account_b, amount)
end
private
def debit(account, amount)
account.balance -= amount
end
def credit(account, amount)
account.balance += amount
end
end
savings = Account.new(100)
checking = Account.new(200)
transaction = Transaction.new(checking, savings)
transaction.transfer(50)