instance method adding another instance method to the class

Discussion in 'Ruby' started by Raj Singh, May 29, 2008.

  1. Raj Singh

    Raj Singh Guest

    class Person
    end

    p = Person.new

    def p.something
    def speaks
    puts 'i speak'
    end
    end

    p.something
    Person.new.speaks


    I am trying to understand why the last line is working.

    When p.something is executed then the self is 'p object'. Now method
    speaks is being defined while the self is p. Since speaks is an instance
    method a method should be defined in p's metaclass. But p's meta class
    is not Person.

    Any one cares to explain how method speaks get defined as an instance
    method for Person class.
    --
    Posted via http://www.ruby-forum.com/.
    Raj Singh, May 29, 2008
    #1
    1. Advertising

  2. Raj Singh

    Dave Bass Guest

    Raj Singh wrote:
    > Any one cares to explain how method speaks get defined as an instance
    > method for Person class.


    It's not necessary to instantiate Person; changing the last line to
    Person.speaks also works. This indicates that speak is being defined as
    a class method. This can be confirmed if you put a "p self" line in:

    class Person
    end

    p = Person.new

    def p.something
    def speaks
    puts 'i speak'
    p self
    end
    end

    p.something
    Person.speaks

    which gives:

    i speak
    Person

    How it works is beyond me though.

    --
    Posted via http://www.ruby-forum.com/.
    Dave Bass, May 29, 2008
    #2
    1. Advertising

  3. On Thu, May 29, 2008 at 5:31 PM, Dave Bass <> wrote:
    > Raj Singh wrote:
    >> Any one cares to explain how method speaks get defined as an instance
    >> method for Person class.

    >
    > It's not necessary to instantiate Person; changing the last line to
    > Person.speaks also works. This indicates that speak is being defined as
    > a class method. This can be confirmed if you put a "p self" line in:
    >
    > class Person
    > end
    >
    > p = Person.new
    >
    > def p.something
    > def speaks
    > puts 'i speak'
    > p self
    > end
    > end
    >
    > p.something
    > Person.speaks
    >
    > which gives:
    >
    > i speak
    > Person
    >
    > How it works is beyond me though.


    It's because a nested def doesn't define a method in the class of the
    receiver of the outer method. So in this case it's just as if the code
    was written simply:

    def speaks
    puts "I speak
    end

    except that this doesn't get evaluated until the something method is run.

    So it ends up defining this method, as all top-level methods are, in
    the Kernel module, so any object will respond to speaks.

    To get what I think the OP intended, which is to define speaks as a
    singleton method when the singleton method something is run, try

    def p.something
    def self.speaks
    puts "I speak"
    end
    end

    --
    Rick DeNatale

    My blog on Ruby
    http://talklikeaduck.denhaven2.com/
    Rick DeNatale, May 29, 2008
    #3
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Replies:
    3
    Views:
    917
    Roedy Green
    Jan 28, 2008
  2. marekw2143
    Replies:
    3
    Views:
    1,350
    marekw2143
    Jul 25, 2009
  3. Martin P. Hellwig
    Replies:
    1
    Views:
    365
    Martin P. Hellwig
    Mar 26, 2010
  4. Greg Hauptmann
    Replies:
    9
    Views:
    233
    Loren Segal
    Jun 16, 2008
  5. Chuck Remes
    Replies:
    3
    Views:
    172
    hemant
    Aug 12, 2010
Loading...

Share This Page