Forum: Ruby "Declaring" private instance variables

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Eli B. (Guest)
on 2006-05-19 14:15
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
Pat M. (Guest)
on 2006-05-19 14:30
(Received via mailing list)
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
unknown (Guest)
on 2006-05-19 14:33
(Received via mailing list)
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 :-)

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


:-)
Eli B. (Guest)
on 2006-05-19 14:47
> 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 :-) 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.
unknown (Guest)
on 2006-05-19 14:54
(Received via mailing list)
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 :-) 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 :-)


David
Uncutstone W. (Guest)
on 2006-05-19 16:47
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.
unknown (Guest)
on 2006-05-19 17:53
(Received via mailing list)
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.
Austin Z. (Guest)
on 2006-05-19 18:05
(Received via mailing list)
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
unknown (Guest)
on 2006-05-19 18:29
(Received via mailing list)
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.
Eli B. (Guest)
on 2006-05-19 20:45
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?
Logan C. (Guest)
on 2006-05-20 01:36
(Received via mailing list)
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.
This topic is locked and can not be replied to.