«

»

Sep 11

methods, public_methods, and private_methods

Ruby’s Object has a method, methods. You can use it to see the methods which an object has. Sort of. In this post I’m examining methods, public_methods, and private_methods as well as some of their implications.

Let’s take this simple class and look at it:

One thing to remember is that once the private keyword is seen within a source file, any subsequent methods are private, unless they follow either public or protected. The above class illustrates this. However, in practice it is not a good idea to mix public and private methods like this.

Ok, let’s take a look at using this class:

You might have noticed above the my_methods method. This is a not a part of the ruby language, but a helper method which I use in my .irbrc and looks like this:

I think it’s useful for querying an object for it’s public methods.

The interesting bit here is that the methods method returns the same as the public_methods method. There’s a lot of methods here beyond what we’ve defined — this is because of the methods defined by Object:

Ok, that makes more sense. Here we see our two methods. However, the initialize method is missing — this is because it’s not a public method of the instance, but rather a private method of the class(Note: see Class is Class and Instance, Instance, and never the twain shall meet for why the edit is here):

So let’s look at the private methods:

Huh, there’s a couple of methods we didn’t define. Nor are they part of Object. The reason for this is that we’ve eliminated the private class methods of Object, but we haven’t eliminated the private instance methods:

So these methods are private. That means we can’t invoke them from outside the instance, right?

Well, not precisely — there’s a trick we can use to do so:

In this case it works. That’s because we’re invoking the public method send, which then, from inside the instance invokes the private method. Is it necessarily a good idea to take advantage of this? No, usually methods are private for a reason. But, it still works.

2 comments

1 ping

  1. Pit Capitain

    Matt, #initialize is a private *instance* method, as you can see in your irb output of m.private_methods. It wouldn’t make sense for #initialize to be a class method. The class MethodsTest also has a method #initialize, which is the instance method defined in Class, the class of MethodsTest.

  2. Matt Williams

    Hmmm. Playing around some more with irb, I see you’re right:

    irb(main):010:0> class Foo
    irb(main):011:1> def Foo.bar
    irb(main):012:2> end
    irb(main):013:1> end
    => nil
    irb(main):014:0> class Fud end
    => nil
    irb(main):016:0> f=Fud.new
    => #
    irb(main):017:0> f.methods
    => [“inspect”, “my_methods”, “tap”, “clone”, “public_methods”, “__send__”, “object_id”, “instance_variable_defined?”, “equal?”, “freeze”, “extend”, “send”, “methods”, “where_is_this_defined”, “hash”, “dup”, “to_enum”, “instance_variables”, “eql?”, “instance_eval”, “id”, “singleton_methods”, “taint”, “enum_for”, “frozen?”, “instance_variable_get”, “instance_of?”, “display”, “to_a”, “method”, “type”, “instance_exec”, “protected_methods”, “==”, “===”, “instance_variable_set”, “kind_of?”, “respond_to?”, “to_s”, “class”, “__id__”, “tainted?”, “=~”, “private_methods”, “untaint”, “nil?”, “is_a?”]
    irb(main):018:0> f.methods.include? “bar”
    => false
    irb(main):019:0> Fud.methods.include? “bar”
    => true
    irb(main):020:0> g=Foo.new
    => #
    irb(main):021:0> g.methods.include? “bar”
    => false
    irb(main):022:0> class Groo
    irb(main):023:1> def Groo.bar
    irb(main):024:2> puts “I’ve got class”
    irb(main):025:2> end
    irb(main):026:1> def bar
    irb(main):027:2> puts “I don’t have class”
    irb(main):028:2> end
    irb(main):029:1> end
    => nil
    irb(main):030:0> Groo.bar
    I’ve got class
    => nil
    irb(main):031:0> g=Groo.new
    => #
    irb(main):032:0> g.bar
    I don’t have class
    => nil
    irb(main):033:0> class Gruff end
    => nil
    irb(main):035:0> Gruff.bar
    I’ve got class
    => nil
    irb(main):036:0> h=Gruff.new
    => #
    irb(main):037:0> h.bar
    I don’t have class
    => nil

    It still would make sense to me that the “constructor” is a class level method, but given that #initialize is an instance variable that could lend itself to interesting side effects…

  1. Ramblings » Blog Archive » Class is Class, and Instance, Instance, and never the twain shall meet

    […] about methods, it’s inspired/spurred by a comment on methods, public_methods, and private_methods by Pit Captain. It also corrects some misconceptions I had (and may have (wrongly) given […]

Leave a Reply

%d bloggers like this: