"Declaring" private instance variables


#1

Hello fellow Rybuists,

One thing I like about C++'s OO is the way in which all class & instance
variables are conveniently “declared” in respective public and private
sections. This makes the code easier to understand, since the
declaration is a good place to comment on the variable, explaining how
it is used.

Ruby has several options regarding this, but nothing of a concensus, it
seems. Public members can be declared with ‘attr’ and friends. But what
about private memberes. For now I find it convenient to preallocate
those in ‘initialize’. What are the approaches you use ?

My aim is to enhance the readability of my class. It won’t affect its
usage, just its comprehension when I return in the future trying to grok
how it works.

Eli


#2

On 5/19/06, Eli B. removed_email_address@domain.invalid wrote:

about private memberes. For now I find it convenient to preallocate

Actually, the attr-family is just some metaprogramming to create new
methods. There are no public instance variables.

Setting your variables up in initialize is fine, or when they’re first
used. Doesn’t really matter.

Pat


#3

Hi –

On Fri, 19 May 2006, Eli B. wrote:

about private memberes. For now I find it convenient to preallocate
those in ‘initialize’. What are the approaches you use ?

The behaviors provided by attr_* are implemented using instance
variables, but that’s not the whole instance variable story. I’m not
quite sure which constructs you’re specifically thinking of, but if
you want your attr_* methods private, just do:

class C
private
attr_accessor :x

 # etc.

end

The privacy you’re gaining here is the privacy of the x and x=
methods. That’s separate from the fact that @x is “private” (i.e.,
only visible to the instance whose variable it is). Even non-private
attr_*-generated methods use instance variables. (Usually the point
is to make the object’s state less private :slight_smile:

You can always just use an instance variable on its own, too.

My aim is to enhance the readability of my class. It won’t affect its
usage, just its comprehension when I return in the future trying to grok
how it works.

I don’t think you’ll get much clearer than:

@n = 1

:slight_smile:


#4

The behaviors provided by attr_* are implemented using instance
variables, but that’s not the whole instance variable story. I’m not
quite sure which constructs you’re specifically thinking of, but if
you want your attr_* methods private, just do:

class C
private
attr_accessor :x

 # etc.

end

The privacy you’re gaining here is the privacy of the x and x=
methods. That’s separate from the fact that @x is “private” (i.e.,
only visible to the instance whose variable it is). Even non-private
attr_*-generated methods use instance variables. (Usually the point
is to make the object’s state less private :slight_smile: too.

Interesting - I didn’t know that it’s possible to have private variables
by means of attr_* in ‘private’. Thanks

My aim is to enhance the readability of my class. It won’t affect its
usage, just its comprehension when I return in the future trying to grok
how it works.

I don’t think you’ll get much clearer than:

@n = 1

Sure, the question is where to put this line. I find that when such
“declarations” are interspersed in various methods of a 300-line class,
it makes comprehension more difficult.


#5

Hi –

On Fri, 19 May 2006, Eli B. wrote:

 # etc.

end

The privacy you’re gaining here is the privacy of the x and x=
methods. That’s separate from the fact that @x is “private” (i.e.,
only visible to the instance whose variable it is). Even non-private
attr_*-generated methods use instance variables. (Usually the point
is to make the object’s state less private :slight_smile: too.

Interesting - I didn’t know that it’s possible to have private variables
by means of attr_* in ‘private’. Thanks

You’re actually getting private methods, not variables. The methods
happen to use instance variables internally, but that’s a separate
matter from their access level.

“declarations” are interspersed in various methods of a 300-line class,
it makes comprehension more difficult.

It’s not really a declaration, though; it’s just a variable
assignment. Just put it somewhere before you need the variable to
have that value :slight_smile:

David


#6

Eli B. wrote:

Hello fellow Rybuists,

One thing I like about C++'s OO is the way in which all class & instance
variables are conveniently “declared” in respective public and private
sections. This makes the code easier to understand, since the
declaration is a good place to comment on the variable, explaining how
it is used.

Ruby has several options regarding this, but nothing of a concensus, it
seems. Public members can be declared with ‘attr’ and friends. But what
about private memberes. For now I find it convenient to preallocate
those in ‘initialize’. What are the approaches you use ?

My aim is to enhance the readability of my class. It won’t affect its
usage, just its comprehension when I return in the future trying to grok
how it works.

IMHO, declaration of private intance variable is a deep-rooted static
way of thinking. But ruby is dynamic, in ruby, I think we need think
dynamically. So, acctually, we don’t need any instance variable
declaration. Any instance variable can be added at the time you need.
That’s ruby’s way.


#7

On May 19, 2006, at 6:31 AM, removed_email_address@domain.invalid wrote:

end
Is there any existing (or previously proposed) way of ‘scoping’ the
behavior
of private? I’m thinking something like:

class A
attr_accessor :a
private {
attr_accessor :b
}
end

I’m aware that you can ‘toggle’ visibility:

class A
attr_accessor :a # public
private
attr_accessor :b # private
public
attr_accessor :c # public
end

but it would seem some sort of block/scope notation would be cleaner.

Gary W.


#8

On 5/19/06, removed_email_address@domain.invalid removed_email_address@domain.invalid wrote:

but it would seem some sort of block/scope notation would be cleaner.
No, there isn’t. Why would you want that? I see no advantage to it,
and it’s odd. I prefer this, though:

class A
attr_accessor :a, :b, :c
private :b, :b=
end

-austin


#9

unknown wrote:

Interesting - I didn’t know that it’s possible to have private variables
by means of attr_* in ‘private’. Thanks

You’re actually getting private methods, not variables. The methods
happen to use instance variables internally, but that’s a separate
matter from their access level.

I also get a warning on this:

78: warning: private attribute?


#10

On May 19, 2006, at 10:03 AM, Austin Z. wrote:

No, there isn’t. Why would you want that? I see no advantage to it,
and it’s odd. I prefer this, though:

class A
attr_accessor :a, :b, :c
private :b, :b=
end

Seems like a lot of redundancy there. You are typing :b three times.
What if you had three public attributes and three private?

class A
attr_accessor :a, :b, :c, :d, :e, :f
private :d, :d=, :e, :e=, :f, :f=
end

vs.

class A
attr_accessor :a, :b, :c
private { attr_accessor :d, :e, :f }
end

The hidden state behavior of public, private, protected (changing the
default visibility of method definitions) always seems a little
awkward to me.
When they are used with arguments it doesn’t seem as awkward.

Gary W.


#11

On May 19, 2006, at 10:26 AM, removed_email_address@domain.invalid wrote:

class A
Gary W.

Here’s an implementation. I almost laughed at myself when i figured
out the right way to do it, trying to use all sorts of
Binding.of_caller type magic to get the toggle methods to work
properly, then I realized the correct way to do it.

% cat block_private.rb
class Module
def private_body(&block)
old_meths = instance_methods
class_eval(&block)
new_meths = instance_methods - old_meths
new_meths.each do |meth|
private(meth)
end
nil
end
end

class A
def pub_meth
puts “This is fine”
end

private_body do
def priv_meth
puts “Can’t call me.”
end
end

def pub_meth2
puts “Yay!”
end
end

a = A.new
a.pub_meth
a.pub_meth2
a.priv_meth

% ruby block_private.rb
-:32: private method `priv_meth’ called for #<A:0x1e82fc>
(NoMethodError)
This is fine
Yay!

The misordered output is an artifact of my shiny new script for doing
examples.