Method explanation

Hello,

This is a beginner question, am going through a book where it gives an
example to show encapsulation, however, within the example itself it
uses concepts that it hasn't previously explained properly, leaving me
somewhat confused.

I was hoping someone could possibly explain what's going on. Here's the
code example;

···

------------------
class Person
  def initialize(age)
    @age = age
  end

  def age
    @age
  end

  def age_difference_with(other_person)
    (self.age - other_person.age).abs
  end

  protected :age
end

fred = Person.new(34)
chris = Person.new(25)
puts chris.age_difference_with(fred)

-----------------

The part that I don't understand is "puts
chris.age_difference_with(fred)". I realise that Chris/fred are both
object instances who have a set age. I understand the (fred) parameter,
as that correlates to the object parameter in the age_difference_with
method (other_person).

It's the "chris." part that I really don't get. How does "self.age" in
the method correlate with the "chris."? (I don't fully understand
"self" part either. All I know is that it can be renamed and is used as
a method name ie.

"def self.count
@@count_object_instances
end"

and it is considered a class method)

Thanks for any explanation.

--
Posted via http://www.ruby-forum.com/.

The "self" keyword is one of the great things about Ruby :slight_smile:
It can mean different things in different context.

When you write "self" inside an instance method, you're referring to the
current instance. So "self.age" is referring to the age of chris or
fred; whoever called the method.

When you use "self.method" to define a method, "self" refers to the
Class. This means that the method is a "Class method", which belongs to
the Class blueprint, and is independent of instances.

What "chris.self" is pointing to is this:

  def age
    @age
  end

Because that method doesn't start with "self." (or one of the other ways
of defining class methods), it is an "instance method", so it belongs to
that instance of the class: "chris".

This can probably explain it better than I can:
http://www.jimmycuadra.com/posts/self-in-ruby (top Google result for
ruby self)

···

--
Posted via http://www.ruby-forum.com/.

hi Joel Pearson

you said:When you use "self.method" to define a method, "self" refers to
the
Class. This means that the method is a "Class method", which belongs to
the Class blueprint, and is independent of instances.

I don't think it's completely independent of instances, because there is
not much difference between normal method and class method expect it's
defined inside class Class. Your class name will act as object to that
method.So it's an instance method to your class name. For an example,

class Raj
    def self.hi
        puts 'hi'
    end
end

Now I can access this method as Raj.hi it's because Raj is an object of
class Class and this hi method is defined inside class Class.

···

--
Posted via http://www.ruby-forum.com/.

hi tamouse m

I am saying Raj is the object of class Class, So you are directly
accessing like Raj.hi and

raj = Raj.new
puts raj.hi

You can't access like this because hi is not in Raj class but it's in
the class Class,So Raj is the object to access class Class.

I know "def self.hi" and "def hi" both are not same, but both functions
are defined in different class so we are using different object to
access that.

···

--
Posted via http://www.ruby-forum.com/.

I feel I should add a little here. I'll do it illustratively using code
examples, hopefully people can understand the underlying message.

1. Define a method in a class, create an instance, and call the method
on the instance.

  class Foo
    # Define a method
    # Inside that method, 'self' refers to the instance object.
    def asd
      p self
    end
  end
  my_foo = Foo.new
  my_foo.asd #=> "#<Foo:0x007fec18284568>"

We can't do things like `Foo.asd`, because we haven't added a class
method to Foo.

2. A couple of ways of defining class methods:

  # Open the class 'Foo'
  # Inside the class definition (but not inside methods),
  # 'self' refers to the class object.
  class Foo
    # Define a class method
    # Inside it, 'self' refers to the class object.
    def self.asd
      p self
    end
  end
  Foo.asd #=> "Foo"

  # Like above, but we don't rely on the word 'self'
  # to refer to the class object.
  class Bar
    def Bar.asd
      p self
    end
  end
  Bar.asd #=> "Bar"

  # Like above, but doing things in different scopes.
  class Baz
  end
  def Baz.asd
    p self
  end
  Baz.asd #=> "Baz"

...etc. Note that you can use 'def obj.meth' to arbitrarily define
methods directly on the 'obj' (whether or not obj is called 'self' or
not).

What this actually does is define the method on obj's singleton class,
which you can think of as a magic class that has exactly one instance:
obj

It might help, at this point, to remember a couple of things:

1) `class Foo; end` opens (or reopens) the definition of class Foo
2) the word 'Foo' in your code is a constant, and the value of that
constant is an object, and that object is_a? Class
3) this also works: Foo = Class.new

So 'Foo' is just another object, and when you call 'Foo.blah' ruby
searches:
1) Foo.singleton_class, for any methods defined directly on Foo, like
#asd
2) Foo's class, Class, for any instance methods defined there, like
#ancestors
3) ... and on up the inheritance tree, through Module, Object, Kernel,
etc.

It is possible to open (or reopen) an object's singleton class using a
special extension syntax:

  qux = Object.new
  class << qux
    def asd
      p self
    end
  end
  qux.asd #=> "#<Object:0x007fec182ffdd0>

Note that this is essentially the same as `def qux.asd`, but we can do
other things between the 'class <<' and the 'end', e.g.:

  class << qux
    private :asd
    attr_accessor :bob
  end
  qux.bob = 123
  qux.bob #=> 123
  qux.asd #=> NoMethodError: private method `asd' called for
#<Object:0x007fec182ffdd0 @bob=123>

Now, combining this with the fact that a class is just another object,
we can do:

  class Qux
    class << self
      def asd
        p self
      end
      private :asd
      attr_accessor :bob
    end
  end
  Qux.bob = 123
  Qux.bob #=> 123
  Qux.asd #=> NoMethodError: private method `asd' called for Qux:Class

Note that, unless we explicitly write the word 'Class' in the code, or
do some other horrible hackery, we're never adding instance methods to
the Class class. You could do the following:

  class Class
    def banana
      'yes please'
    end
  end

... which would make the following all work:

  Foo.banana #=> "yes please"
  Bar.banana #=> "yes please"
  Integer.banana #=> "yes please"
  Class.banana #=> "yes please"

But that's different from defining 'self.meth' inside a class
definition.

Hope that makes sense.

···

--
Posted via http://www.ruby-forum.com/.

class Raj
  def self.hi
    "#{caller.first}: hi"
  end
end

puts Raj.hi
raj = Raj.new
puts raj.hi

these things are not the same.

···

On Sun, Jan 12, 2014 at 9:05 PM, Raja gopalan <lists@ruby-forum.com> wrote:

hi Joel Pearson

you said:When you use "self.method" to define a method, "self" refers to
the
Class. This means that the method is a "Class method", which belongs to
the Class blueprint, and is independent of instances.

I don't think it's completely independent of instances, because there is
not much difference between normal method and class method expect it's
defined inside class Class. Your class name will act as object to that
method.So it's an instance method to your class name. For an example,

class Raj
    def self.hi
        puts 'hi'
    end
end

Now I can access this method as Raj.hi it's because Raj is an object of
class Class and this hi method is defined inside class Class.

+1 for Matthew Kerwin.

Just to emphasize Matthew's point

class BarClass
  def my_normally_defined_on_BarClass_class
  end

  def self.my_defined_prepended_with_self
  end
end

bar_object = BarClass.new

def bar_object.my_defined_prepended_with_the_object
end

# As the "normal" "methods" of the bar_object are not
# defined on the bar_object itself. But they are
# defined as "instance methods" of its class,
# that is the BarClass.
# So it is the BarClass (as an object of the class Class).
# To define methods of the BarClass, I don't
# define them on the BarClass itself, but on its class.
# And what is the class of the BarClass (object)?
# It's Class (another object :wink: ).

class Class
  def my_normally_defined_on_Class_class
  end
end

BarClass.methods.grep /my/
# => [:my_defined_prepended_with_self, :my_normally_defined_on_Class_class]

BarClass.singleton_methods.grep /my/
# => [:my_defined_prepended_with_self]

bar_object.methods.grep /my/
# => [:my_defined_prepended_with_the_object,
:my_normally_defined_on_BarClass_class]

bar_object.singleton_methods.grep /my/
# => [:my_defined_prepended_with_the_object]

And, Yehuda Katz's post from 2009 still lives!

It's all about self! :slight_smile:

Best regards,
Abinoam Jr.

···

On Mon, Jan 13, 2014 at 3:28 AM, Matthew Kerwin <lists@ruby-forum.com> wrote:

I feel I should add a little here. I'll do it illustratively using code
examples, hopefully people can understand the underlying message.

1. Define a method in a class, create an instance, and call the method
on the instance.

  class Foo
    # Define a method
    # Inside that method, 'self' refers to the instance object.
    def asd
      p self
    end
  end
  my_foo = Foo.new
  my_foo.asd #=> "#<Foo:0x007fec18284568>"

We can't do things like `Foo.asd`, because we haven't added a class
method to Foo.

2. A couple of ways of defining class methods:

  # Open the class 'Foo'
  # Inside the class definition (but not inside methods),
  # 'self' refers to the class object.
  class Foo
    # Define a class method
    # Inside it, 'self' refers to the class object.
    def self.asd
      p self
    end
  end
  Foo.asd #=> "Foo"

  # Like above, but we don't rely on the word 'self'
  # to refer to the class object.
  class Bar
    def Bar.asd
      p self
    end
  end
  Bar.asd #=> "Bar"

  # Like above, but doing things in different scopes.
  class Baz
  end
  def Baz.asd
    p self
  end
  Baz.asd #=> "Baz"

...etc. Note that you can use 'def obj.meth' to arbitrarily define
methods directly on the 'obj' (whether or not obj is called 'self' or
not).

What this actually does is define the method on obj's singleton class,
which you can think of as a magic class that has exactly one instance:
obj

It might help, at this point, to remember a couple of things:

1) `class Foo; end` opens (or reopens) the definition of class Foo
2) the word 'Foo' in your code is a constant, and the value of that
constant is an object, and that object is_a? Class
3) this also works: Foo = Class.new

So 'Foo' is just another object, and when you call 'Foo.blah' ruby
searches:
1) Foo.singleton_class, for any methods defined directly on Foo, like
#asd
2) Foo's class, Class, for any instance methods defined there, like
#ancestors
3) ... and on up the inheritance tree, through Module, Object, Kernel,
etc.

It is possible to open (or reopen) an object's singleton class using a
special extension syntax:

  qux = Object.new
  class << qux
    def asd
      p self
    end
  end
  qux.asd #=> "#<Object:0x007fec182ffdd0>

Note that this is essentially the same as `def qux.asd`, but we can do
other things between the 'class <<' and the 'end', e.g.:

  class << qux
    private :asd
    attr_accessor :bob
  end
  qux.bob = 123
  qux.bob #=> 123
  qux.asd #=> NoMethodError: private method `asd' called for
#<Object:0x007fec182ffdd0 @bob=123>

Now, combining this with the fact that a class is just another object,
we can do:

  class Qux
    class << self
      def asd
        p self
      end
      private :asd
      attr_accessor :bob
    end
  end
  Qux.bob = 123
  Qux.bob #=> 123
  Qux.asd #=> NoMethodError: private method `asd' called for Qux:Class

Note that, unless we explicitly write the word 'Class' in the code, or
do some other horrible hackery, we're never adding instance methods to
the Class class. You could do the following:

  class Class
    def banana
      'yes please'
    end
  end

... which would make the following all work:

  Foo.banana #=> "yes please"
  Bar.banana #=> "yes please"
  Integer.banana #=> "yes please"
  Class.banana #=> "yes please"

But that's different from defining 'self.meth' inside a class
definition.

Hope that makes sense.

--
Posted via http://www.ruby-forum.com/\.