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.
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.
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.
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
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.
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
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.
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.
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 forum is not affiliated to the Ruby language, Ruby on Rails framework, nor any Ruby applications discussed here.