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

By Koen

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.

Share This

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

  1. jc Says:

    Private methods bad for reusability?

    I love ruby and all, but encapsulation is actually GOOD for reusability. I wish they’d fix some of this stuff up to make it a little more sturdy.

    So many things in Ruby are along the lines of “you can, but you shouldn’t”. Guess this is just one of those things…

  2. Nicolas Sanguinetti Says:

    Actually, data encapsulation is bad for reusability in general, yes. As a library vendor, you never know the needs of your clients, so maybe you thought out a certain way to interact with your library from the outside, but maybe you have a lot of users that need to interact with it in a different way, that you hadn’t foresaw.

    So, you publish your code and your classes without all the “private” thingies, and then you publish your interfaces with the contract you designed. That just guides people along the “suggested path” for your library, but allows clients to leverage the full power of your code :)

    And please, dont answer with the “we have to protect them from possible mistakes of using the code”, if you dont assume programmers are intelligent enough, then why the hell are you giving them your library, if you are so smarter than them? :P

  3. Mark Murphy Says:

    FYI, Ruby and Java were first developed around the same time, and both were released to the public in 1995. If the private keyword existed from the beginning, then Ruby would not have been following Java’s lead, since it’s unlikely that Matz (Ruby) or James Gosling (Java) knew much about what the other was doing. Both languages followed the release of C++.

  4. Carl Graff Says:

    Actually I think data encapsulation protects the author just as much as the users of a “library”. It allows the underlying implementation to be refactored with a degree of protection.

    In any event you can override the private methods dynamically for example the CSV library:

    class CSV
    class

  5. Carl Graff Says:

    Oops I think the code example got cut off:

    class CSV
    class

  6. Carl Graff Says:

    Ok one more try :-(


    class CSV
    class

  7. Carl Graff Says:

    Well C@3p. This guy is way smarter than me and a good video:
    http://video.google.com/videoplay?docid=-3733345136856180693

Leave a Reply


Close
E-mail It
Socialized through Gregarious 42