Access modifier : private

D

Dharmarth Shah

Hi!

I'm missing some core ruby concept here that I just can't figure out;
any assistance would be excellent and welcome:

I came to know from various posts that Class level varibales are
shared among its subclasses in 1.8.

But my confusion is, even though i mark it as private, it is
accessible in subclass. See example below for more clarity on doubt.

class Test1
private
@@v=10
end

class Test2 < Test1
def pr
@@v=12
puts @@v
end
end

Test2.new.pr

~Dharmarth
 
S

Stefano Crocco

Alle sabato 24 novembre 2007, Dharmarth Shah ha scritto:
Hi!

I'm missing some core ruby concept here that I just can't figure out;
any assistance would be excellent and welcome:

I came to know from various posts that Class level varibales are
shared among its subclasses in 1.8.

But my confusion is, even though i mark it as private, it is
accessible in subclass. See example below for more clarity on doubt.

class Test1
private
@@v=10
end

class Test2 < Test1
def pr
@@v=12
puts @@v
end
end

Test2.new.pr

~Dharmarth

First of all, private only works for instance methods, not for variables,
either instance variables or class variables, which are always private.
Second, the meaning of "private" in ruby is different from what you have in
other languages such as C++. In ruby, "private" only means you can't call it
with a receiver (i.e, using the form receiver.method). This means that a
method declared private in a class can be called in a subclass. The same is
true for instance variables (writing rec.@var gives a syntax error, which is
the reason instance variables are always private). Here are some examples:

class A
def initialize
@x=1
end

def m1
puts "m1 calling m"
m
end

def m2
puts "m2 calling self.m"
self.m
end

def m3 other
puts "m3 calling m on other instance of class A"
other.m
end

private
def m
puts "m"
end

end

class B < A

def mb1
puts "@x is: #{@x}"
end

def mb2
puts "mb2 calling m"
m
end

end

After loading the previous code in IRB (from the file test_private.rb), I run
the methods defined for A and B, with the following results:
irb(main):001:0> require 'test_private'
=> true
irb(main):002:0> a = A.new
=> #<A:0xb78da7b8 @x=1>
irb(main):003:0> a.m1
m1 calling m
m
=> nil
irb(main):004:0> a.m2
m2 calling self.m
NoMethodError: private method `m' called for #<A:0xb78da7b8 @x=1>
from ./prova.rb:14:in `m2'
from (irb):4
irb(main):005:0> a.m3 A.new
m3 calling m on other instance of class A
NoMethodError: private method `m' called for #<A:0xb78d44f8 @x=1>
from ./prova.rb:19:in `m3'
from (irb):6
irb(main):006:0> b = B.new
=> #<B:0xb78d257c @x=1>
irb(main):007:0> b.mb1
@x is: 1
=> nil
irb(main):008:0> b.mb2
mb2 calling m
m
=> nil

A#m1, obviously, works. A#m2 doesn't work because it calls m using a receiver,
which is forbidden (even when the receiver is the implicit receiver, self).
A#m3 doesn't work because it calls m with a receiver (even if of the same
class as self). B#bm1 works, because the instance variable is called without
a receiver. B#mb2 works, because it's calling the method without the
receiver. The fact that the method is private doesn't matter.

I hope this helps

Stefano
 
D

Dharmarth Shah

Thanks a lot Stefano! That was really helpful.

One more help.

What's the rationale in sharing Class level variables with subclasses?
Is there any way to restrict Class level variables and Class level
methods to restrict to class itself?

~Dharmarth
 
P

Phrogz

Thanks a lot Stefano! That was really helpful.

One more help.

What's the rationale in sharing Class level variables with subclasses?
Is there any way to restrict Class level variables and Class level
methods to restrict to class itself?

Instead of using class level variables, use instance variables of the
class itself. It's what most people want anyhow:

irb(main):001:0> class Foo
irb(main):002:1> @jim = :foo
irb(main):003:1> class << self
irb(main):004:2> attr_accessor :jim
irb(main):005:2> end
irb(main):006:1> end

irb(main):007:0> class Bar < Foo
irb(main):008:1> @jim = :bar
irb(main):011:1> end

irb(main):012:0> Foo.jim
=> :foo

irb(main):013:0> Bar.jim
=> :bar

irb(main):014:0> Foo.jim = 42
=> 42

irb(main):015:0> Bar.jim
=> :bar

irb(main):016:0> Bar.jim = 'whee'
=> "whee"

irb(main):017:0> Foo.jim
=> 42

etc.
 

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

No members online now.

Forum statistics

Threads
473,769
Messages
2,569,580
Members
45,054
Latest member
TrimKetoBoost

Latest Threads

Top