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.
Fc761ccaf6c0d7d977e2959f9bfebd06?d=identicon&s=25 Eli Bendersky (eliben)
on 2006-05-19 12: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
42172acdf3c6046f84d644cb0b94642c?d=identicon&s=25 Pat Maddox (pergesu)
on 2006-05-19 12:30
(Received via mailing list)
On 5/19/06, Eli Bendersky <eliben@gmail.com> 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
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-05-19 12:33
(Received via mailing list)
Hi --

On Fri, 19 May 2006, Eli Bendersky 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


:-)
Fc761ccaf6c0d7d977e2959f9bfebd06?d=identicon&s=25 Eli Bendersky (eliben)
on 2006-05-19 12: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.
1fba4539b6cafe2e60a2916fa184fc2f?d=identicon&s=25 unknown (Guest)
on 2006-05-19 12:54
(Received via mailing list)
Hi --

On Fri, 19 May 2006, Eli Bendersky 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
288733e11db1c6dbbf50871d2c6738c6?d=identicon&s=25 Uncutstone Wu (uncutstone)
on 2006-05-19 14:47
Eli Bendersky 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.
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 unknown (Guest)
on 2006-05-19 15:53
(Received via mailing list)
On May 19, 2006, at 6:31 AM, dblack@wobblini.net 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 Wright
31ab75f7ddda241830659630746cdd3a?d=identicon&s=25 Austin Ziegler (Guest)
on 2006-05-19 16:05
(Received via mailing list)
On 5/19/06, gwtmp01@mac.com <gwtmp01@mac.com> 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
E7559e558ececa67c40f452483b9ac8c?d=identicon&s=25 unknown (Guest)
on 2006-05-19 16:29
(Received via mailing list)
On May 19, 2006, at 10:03 AM, Austin Ziegler 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 Wright
Fc761ccaf6c0d7d977e2959f9bfebd06?d=identicon&s=25 Eli Bendersky (eliben)
on 2006-05-19 18: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?
E34b5cae57e0dd170114dba444e37852?d=identicon&s=25 Logan Capaldo (Guest)
on 2006-05-19 23:36
(Received via mailing list)
On May 19, 2006, at 10:26 AM, gwtmp01@mac.com wrote:

>
> class A
> Gary Wright
>
>
>
>

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.