private vs. protected question

K

Kaye Ng

From a book I'm reading:
------------------------------------------------------------------------
class Person
def initialize(age)
@age =3D age
end

def age
@age
end

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

protected :age
end

fred =3D Person.new(34)
chris =3D Person.new(25)
puts chris.age_difference_with(fred)
puts chris.age
-------------------------------------------------------------------------=

results in:

9
:20: protected method 'age' called for #<Person:0x1e5f28 @age=3D25>
(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=3D25> (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=E2=80=99s 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/.=
 
7

7stud --

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=E2=80=99s because private makes methods accessible onl= y by
methods of a specific
object."

From the statement, "...because private makes methods accessible only b= y
methods of a specific
object.", I'm assuming that it also means 'accessible only by methods o= f
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 =3D 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 =3D 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 =3D 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 =3D 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/.=
 
7

7stud --

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>'
 
7

7stud --

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.
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,969
Messages
2,570,161
Members
46,705
Latest member
Stefkari24

Latest Threads

Top