What is this? From this page you can use the Social Web links to save Ruby's "private": not as Private as You Expect to a social bookmarking site, or the E-mail form to send a link via e-mail.

Social Web

E-mail

E-mail It
April 24, 2007

Ruby’s “private”: not as Private as You Expect

Posted in: ruby

I expect that, if a language borrows a concept from another language, and if that language even uses the same name for the concept, the concept also has the same semantics. That is not the case for “private” access control in Ruby.

In Java and C++, the sematics of the “private” access modifier for a method is: the method can only be called by methods of the class that declares the private method.

In Ruby, the semantics is (taken from the pickaxe book, page 35): private methods can be called only in the context of the current object. A bit further in the book: The difference between “protected” and “private” is fairly subtle and is different in Ruby than in most common OO languages.

Indeed, the difference is subtle, certainly for C++ and Java developers learning Ruby. As the sematics above already indicate, C++ and Java have a class focus, while Ruby has an instance focus. Private in C++ and Java means: private to the class. In Ruby, it means: private to the instance.

There is another aspect of the semantics that is important. In C++ and Java, a private method can be called on a different instance than the one executing the current method. In Ruby, private methods can only be invoked on the same instance, which is enforced syntactically: private methods can only be invoked without a receiver or with self.

Because in Ruby private methods are private to an instance, they can be invoked by methods in a subclass, illustrated by the following code snippet:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class Superclass
    private
        def m1()
            puts "Superclass.m1"
        end
end
 
class Subclass < Superclass
    public
        def m2()
            m1()
            puts "Subclass.m2"
        end
end
 
Subclass.new().m2()

The output of the program is:

irb(main):017:0> Subclass.new().m2()
Superclass.m1
Subclass.m2
=> nil

Private methods can also be overridden, as shown in this code snippet:

17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
class Superclass
    private
        def m()
            puts "Superclass.m"
        end
end
 
class Subclass < Superclass
    public
        def m()
            super()
            puts "Subclass.m"
        end
end
 
Subclass.new.m()

The output of the program is:

irb(main):017:0> Subclass.new.m()
Superclass.m
Subclass.m
=> nil

A singleton method can even override a private method of the class of the instance, as illustrated by this code snippet:

33
34
35
36
37
38
39
40
41
42
43
44
45
class MyClass
    private
        def m()
            puts "MyClass.m"
        end
end
 
object = MyClass.new()
def object.m()
    super()
    puts "object.m"
end
object.m()

The output of the program is:

irb(main):013:0> object.m()
MyClass.m
object.m
=> nil

The conclusion is that Ruby has no way to make methods private in the C++ and Java sense. In my opinion, that is a good thing, because private methods are bad for reusability. But I do not believe that using the word “private” was a good choice.


Return to: Ruby’s “private”: not as Private as You Expect