Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > comp.lang.ruby > #2578 > unrolled thread

private vs. protected question

Started byKaye Ng <sbstn26@yahoo.com>
First post2011-04-09 05:24 -0500
Last post2011-04-09 17:11 -0500
Articles 4 — 2 participants

Back to article view | Back to comp.lang.ruby


Contents

  private vs. protected question Kaye Ng <sbstn26@yahoo.com> - 2011-04-09 05:24 -0500
    Re: private vs. protected question 7stud -- <bbxx789_05ss@yahoo.com> - 2011-04-09 14:35 -0500
      Re: private vs. protected question 7stud -- <bbxx789_05ss@yahoo.com> - 2011-04-09 16:37 -0500
    Re: private vs. protected question 7stud -- <bbxx789_05ss@yahoo.com> - 2011-04-09 17:11 -0500

#2578 — private vs. protected question

FromKaye Ng <sbstn26@yahoo.com>
Date2011-04-09 05:24 -0500
Subjectprivate vs. protected question
Message-ID<bd7050a7923405894788738f2712f45b@ruby-forum.com>
From a book I'm reading:
------------------------------------------------------------------------
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)
puts chris.age
-------------------------------------------------------------------------
results in:

9
:20: protected method 'age' called for #<Person:0x1e5f28 @age=25>
(NoMethodError)
------------------------------------------------------------------------
The first 'puts' line printed '9' on the screen, while the second
resulted
in error.  This is because, like 'private', I cannot use a specific
receiver to call a protected method, correct?

Now I'm going to replace 'protected' with 'private' (and omit the last
line (puts chris.age) ). This would result in:

-------------------------------------------------------------------------
H:/Ruby/Practice/six.rb:9:in `age_difference_with': private method `age'
called for
#<Person:0x19ccf68 @age=25> (NoMethodError)from
H:/Ruby/Practice/six.rb:16:in `<main>'
------------------------------------------------------------------------

Explanation from the book:
" if
age were made private, the preceding example would fail because
other_person.age would
be invalid. That’s because private makes methods accessible only by
methods of a specific
object."

From the statement, "...because private makes methods accessible only by
methods of a specific
object.", I'm assuming that it also means 'accessible only by methods of
a single and CURRENT object', and that current object is 'chris', not
'fred', and that is why it resulted in error.

Am I wrong??
Help please! Thank you!!

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

[toc] | [next] | [standalone]


#2584

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-04-09 14:35 -0500
Message-ID<87c34e7d5a641032304e1f716a3d831e@ruby-forum.com>
In reply to#2578
Kaye Ng wrote in post #991911:
>
> Explanation from the book:
> " if
> age were made private, the preceding example would fail because
> other_person.age would
> be invalid. That’s because private makes methods accessible only by
> methods of a specific
> object."
>
> From the statement, "...because private makes methods accessible only by
> methods of a specific
> object.", I'm assuming that it also means 'accessible only by methods of
> a single and CURRENT object', and that current object is 'chris', not
> 'fred', and that is why it resulted in error.
>
> Am I wrong??
> Help please! Thank you!!

That explanation is about as clear as mud.  The rule for private methods 
is simple:  you cannot call private methods with an explicit receiver. 
Here is an example:

class Dog
  def bark
    puts 'woof'
  end
end

dog = Dog.new
dog.bark

--output:--
woof

In the last line, dog is the 'receiver'.  If bark() is a private method, 
you can't call it with a receiver, so that line would produce an error:

class Dog
  private
  def bark
    puts 'woof'
  end

end

dog = Dog.new
dog.bark

--output:--
prog.rb:10:in `<main>': private method `bark' called for 
#<Dog:0xa1acde0> (NoMethodError)


The implications of the private method rule are a little bit tougher to 
understand.  How can you call bark() on an object if you are not allowed 
to specify the object as the receiver?  Well, in ruby if you call a 
method without a receiver, then something called self becomes the 
receiver by default--self is the implicit receiver.

Therefore, you must understand what object self is equal to in various 
parts of your code:

puts self  #main

class Dog
  puts self  #Dog

  def bark
    puts self  #<Dog:0x8e05c10>,
    puts 'woof'
  end

end

dog = Dog.new
puts dog  #<Dog:0x8e05c10>

dog.bark  #woof

ruby's notation for a dog object is the name of the class plus an id 
number:

#<Dog:0x8e05c10>

Note what self is inside the bark method: it's the same object that 
called the method(compare the id numbers), which is dog.   That means 
you can call private instance methods from inside public instance 
methods:

class Dog
  def do_stuff
    bark
  end

  private
  def bark
    puts 'woof'
  end

end

dog = Dog.new
dog.do_stuff

--output:--
woof

The code works like this:  dog calls do_stuff, so inside do_stuff self 
is equal to dog.  Because the private method bark() is called without a 
receiver, the implicit receiver is self, which in this case is equal to 
dog.  And that is how you call a private method on an object like dog.

The protected method rule states that you can use a receiver to call the 
method--so long as whatever object is self at that time is also an 
object of the same class as the receiver.

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

[toc] | [prev] | [next] | [standalone]


#2585

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-04-09 16:37 -0500
Message-ID<d4c1ef1496fe2233a1355c7812e11a19@ruby-forum.com>
In reply to#2584
7stud -- wrote in post #991945:
>
> The protected method rule states that you can use a receiver to call the
> method--so long as whatever object is self at that time is also an
> object of the same class as the receiver (or a parent or subclass).

I think we need to scratch '(or parent...' off the list:

class Animal
  def meth(obj)
    obj.bark  #self=anim whose class is Animal,
  end         #and Animal is a parent class of obj=dog
end

class Dog < Animal
  protected
  def bark
    puts 'woof'
  end
end

dog = Dog.new
anim = Animal.new
anim.meth(dog)

--output:--
prog.rb:3:in `meth': protected method `bark' called for #<Dog:0x9f8948c> 
(NoMethodError)
  from prog.rb:22:in `<main>'

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

[toc] | [prev] | [next] | [standalone]


#2588

From7stud -- <bbxx789_05ss@yahoo.com>
Date2011-04-09 17:11 -0500
Message-ID<ed6be527beec0f1d92a0ea94d3b9f658@ruby-forum.com>
In reply to#2578
In case all that was too confusing, to sum up:

private:
You can call private methods from inside public methods.

protected:
Protected methods act mostly like private methods, but in some cases you 
are allowed to specify a receiver; those cases occur when self is equal 
to a member of the same class as the receiver or a subclass of the 
receiver.

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

[toc] | [prev] | [standalone]


Back to top | Article view | comp.lang.ruby


csiph-web