Attr_reader/writer vs. attr_accessor w/ access control

it strikes me as curious…

i’ve spent quite a bit of time wrestling with some special attr_* module
methods for use with CGI and i was quite concerned with honoring the full
bredth of reader, writer, and accessor even though it meant more work; that
is to say if i just used accessor it would be a lot easier. and that’s when
it hit me: if i don’t want the external world reading and/or writing to my
object’s instance variables, why wouldn’t i just set the access control to
private (or protected)?

class AttrDemo
attr_accessor :readme
protected :readme=
end

granted this adds in a touch more code, but that’s not the point i’m making.
i’m only pointing out that in effect this serves the same purpose as:

class AttrDemo
attr_reader :readme
end

the only differenece being that in the first example i have a setter method
available to the class itself. fine with me.

except for the fact that instance variables can spring into existence
dynamically, i wonder why they aren’t simply attr_accessor by default and
access control the sole means by which we make them visible or invisible to
the outside.

so, in realizing this, i modified my attr_* methods to return their effected
methods so that i could pass them on to an access control method.
unfortuantely the access control methods will not take arrays. :frowning: it would
be nice if they used #flatten so they could. i tried to rewrite them that
way, but in doing so i lost the ability to have them affect the subsequent
defs when given without arguments. so instead i had to create three new
methods: #privatize, #protect and #publicize to do the job. additionally i
added two new methods #writers and #readers which act as filters, such that
one can do things like:

privatize attr_writer :a  			# a=() is private
protect writers attr_accessor :b  	# a() is public, a=() is protected

does this seem beneficial? is it over kill? is there a better way? what do you
think of the original notion?

···


tom sawyer, aka transami
transami@transami.net

                               .''.
   .''.      .        *''*    :_\/_:     .
  :_\/_:   _\(/_  .:.*_\/_*   : /\ :  .'.:.'.

.’’.: /\ : ./)\ ‘:’* /\ * : ‘…’. -=:o:=-
:/:’.:::. | ’ ‘’ * ‘.’/.’ (/’.’:’.’
: /\ : ::::: = / -= o =- /)\ ’ *
’…’ ‘:::’ === * /\ * .’/.’. ‘._____
* | : |. |’ .—"|
* | _ .–’| || | _| |
* | .-’| __ | | | || |
.-----. | |’ | || | | | | | || |
__’ ’ /"\ | '-."". ‘-’ ‘-.’ '` |.

Hi –

it strikes me as curious…

i’ve spent quite a bit of time wrestling with some special attr_* module
methods for use with CGI and i was quite concerned with honoring the full
bredth of reader, writer, and accessor even though it meant more work; that
is to say if i just used accessor it would be a lot easier. and that’s when
it hit me: if i don’t want the external world reading and/or writing to my
object’s instance variables, why wouldn’t i just set the access control to
private (or protected)?

class AttrDemo
attr_accessor :readme
protected :readme=
end

granted this adds in a touch more code, but that’s not the point i’m making.
i’m only pointing out that in effect this serves the same purpose as:

class AttrDemo
attr_reader :readme
end

the only differenece being that in the first example i have a setter method
available to the class itself. fine with me.

except for the fact that instance variables can spring into existence
dynamically, i wonder why they aren’t simply attr_accessor by default and
access control the sole means by which we make them visible or invisible to
the outside.

This would mean, for one thing, that every object would respond to
every message; there would no longer be a distinction between those
messages an object understood and those it didn’t. If you said:

s = “abc”
s.keys

then you’d get the value of the @keys instance variable of s, instead
of an indication that s doesn’t respond to #keys. And so forth…
Rather more i.v.'s in the landscape than one wants :slight_smile:

so, in realizing this, i modified my attr_* methods to return their effected
methods so that i could pass them on to an access control method.
unfortuantely the access control methods will not take arrays. :frowning: it would
be nice if they used #flatten so they could.

You can use the unary * to un-array your arguments (hey, I never
noticed the similarity of ‘unary’ and ‘unarray’ :slight_smile:

class A
def a; end
def b; end
c = [:a, :b]
private(*c)

end

A.new.b # error: private method ‘b’ called

David

···

On Fri, 10 Jan 2003, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

[snip]

except for the fact that instance variables can spring into existence
dynamically, i wonder why they aren’t simply attr_accessor by default and
access control the sole means by which we make them visible or invisible to
the outside.
[snip]

class AnArrayLikeClass
def size
@size
end

def size= n
raise “THIS MAY NOT MAKE SENSE NO MATTER WHAT THE ACCESS CONTROL”
end
end

i like the

attr_accessor :var
protected :var=

alot though.

-a

···

On Fri, 10 Jan 2003, Tom Sawyer wrote:

====================================

Ara Howard
NOAA Forecast Systems Laboratory
Information and Technology Services
Data Systems Group
R/FST 325 Broadway
Boulder, CO 80305-3328
Email: ahoward@fsl.noaa.gov
Phone: 303-497-7238
Fax: 303-497-7259
====================================

That would not happen if accessors were, say, protected by default. But
then you’d have to ‘publicize’ them anyway, and the situation wouldn’t
be that different from the current one.

OTOH if instance variables were private (not accessible by subclasses)
all this would be much more relevant. I really felt that this was
The Right Thing but matz doesn’t [55201]. I think the main point was
that inheritance is anyway a very strong relationship, so this apparent
breach in data hiding is not that important.

···

On Fri, Jan 10, 2003 at 07:14:24AM +0900, dblack@candle.superlink.net wrote:

except for the fact that instance variables can spring into existence
dynamically, i wonder why they aren’t simply attr_accessor by default and
access control the sole means by which we make them visible or invisible to
the outside.

This would mean, for one thing, that every object would respond to
every message; there would no longer be a distinction between those
messages an object understood and those it didn’t. If you said:

s = “abc”
s.keys

then you’d get the value of the @keys instance variable of s, instead
of an indication that s doesn’t respond to #keys. And so forth…
Rather more i.v.'s in the landscape than one wants :slight_smile:


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

*** PUBLIC flooding detected from erikyyy
THAT’s an erik, pholx… :wink:
– Seen on #LinuxGER

that’s it! that’s it! i’ve been pulling my hair out since the beginning of my
rubyist days deciding when it is the Right Thing to use @var vs. self.var.
And finally it has become clear! the answer is simple: NEVER USE @ OUTSIDE A
GETTER OR SETTER METHOD. what, you say? indeed! in fact, with use of the
shortcut attr_* methods, i never even have to see another instance variable
agian (at least in my code). in almost all cases this means all my attr_*
calls will be attr_accessor, but i can utilize access control to make them
visible or not to the outside rather than by not defining them. i have
already created a fairly goods means to do this concisely, though i would
still like to refine it a bit more:

public
privatize writers attr_accessor :x, :y
protect readers attr_accessor :a, :b

private
publicize attr_accessor :n, :w => :to_s

etc.

examine the first example. i modified #attr_accessor to additionally return
the method symbols it creates:

attr_accessor :x, :y   #--> [:x, :x=, :y, :y=]

then #writers filters those to return only the ones with equals on the end:

writers [:x, :x=, :y, :y=]   #--> [:x=, :y=]

and of course privatize make these two setter methods private.

ah, i like this. only a couple questions left. 1) what’s the best way to
encode what i’ve done above (i think what i have may be too long winded) and
2) given this approach, under what circumstances would one ever need
attr_reader and attr_writer?

thanks millions!

···

On Thursday 09 January 2003 03:57 pm, Mauricio Fernández wrote:

That would not happen if accessors were, say, protected by default. But
then you’d have to ‘publicize’ them anyway, and the situation wouldn’t
be that different from the current one.

OTOH if instance variables were private (not accessible by subclasses)
all this would be much more relevant. I really felt that this was
The Right Thing but matz doesn’t [55201]. I think the main point was
that inheritance is anyway a very strong relationship, so this apparent
breach in data hiding is not that important.


tom sawyer, aka transami
transami@transami.net

                               .''.
   .''.      .        *''*    :_\/_:     .
  :_\/_:   _\(/_  .:.*_\/_*   : /\ :  .'.:.'.

.‘’.: /\ : ./)\ ‘:’* /\ * : ‘…’. -=:o:=-
:/:‘.:::. | ’ ‘’ * ‘.'/.’ (/’.‘:’.’
: /\ : ::::: = / -= o =- /)\ ’ *
‘…’ ‘:::’ === * /\ * .‘/.'. ‘._____
* | : |. |’ .—"|
* | _ .–’| || | _| |
* | .-‘| __ | | | || |
.-----. | |’ | || | | | | | || |
__’ ’ /“\ | '-.”". ‘-’ ‘-.’ '` |.

Hi –

public
privatize writers attr_accessor :x, :y
protect readers attr_accessor :a, :b

private
publicize attr_accessor :n, :w => :to_s

etc.

examine the first example. i modified #attr_accessor to additionally return
the method symbols it creates:

attr_accessor :x, :y #–> [:x, :x=, :y, :y=]

then #writers filters those to return only the ones with equals on the end:

writers [:x, :x=, :y, :y=] #–> [:x=, :y=]

and of course privatize make these two setter methods private.

ah, i like this. only a couple questions left. 1) what’s the best way to
encode what i’ve done above (i think what i have may be too long winded) and

You could do:

attr_accessor :a, :b, :x, :y
private :x=, :y=
protected :a, :b

which is shorter and (I find) easier to read. I think there’s a bit
of a diminishing return, in terms of clarity, in wrapping wrappers in
wrappers beyond a certain point.

  1. given this approach, under what circumstances would one ever need
    attr_reader and attr_writer?

Well, if your approach is to write and use a different set of
method-creation shortcuts, then possibly never :slight_smile: They’re awfully
nice and concise though.

David

···

On Fri, 10 Jan 2003, Tom Sawyer wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav

Then take into account that this goes against matz’s word [55201], for
if @var were never to be used, it would not exist in the language and
instance vars. would be class-local by default.
I have to ponder about this some more, but I have the feeling @iv is
needed sometimes.

···

On Fri, Jan 10, 2003 at 08:38:50AM +0900, Tom Sawyer wrote:

On Thursday 09 January 2003 03:57 pm, Mauricio Fernández wrote:

That would not happen if accessors were, say, protected by default. But
then you’d have to ‘publicize’ them anyway, and the situation wouldn’t
be that different from the current one.

OTOH if instance variables were private (not accessible by subclasses)
all this would be much more relevant. I really felt that this was
The Right Thing but matz doesn’t [55201]. I think the main point was
that inheritance is anyway a very strong relationship, so this apparent
breach in data hiding is not that important.

that’s it! that’s it! i’ve been pulling my hair out since the beginning of my
rubyist days deciding when it is the Right Thing to use @var vs. self.var.
And finally it has become clear! the answer is simple: NEVER USE @ OUTSIDE A
GETTER OR SETTER METHOD. what, you say? indeed! in fact, with use of the


_ _

__ __ | | ___ _ __ ___ __ _ _ __
'_ \ / | __/ __| '_ _ \ / ` | ’ \
) | (| | |
__ \ | | | | | (| | | | |
.__/ _,
|_|/| || ||_,|| |_|
Running Debian GNU/Linux Sid (unstable)
batsman dot geo at yahoo dot com

/*

  • Please skip to the bottom of this file if you ate lunch recently
    
  •                         -- Alan
    

*/
– from Linux kernel pre-2.1.91-1

indeed i think you are probably right. while i think my idea is good one in
theory, it is a bit more difficult (to change habits) in practice. but i feel
good at least in understanding it all more clearly at least.

···

On Thursday 09 January 2003 05:27 pm, dblack@candle.superlink.net wrote:

attr_accessor :a, :b, :x, :y
private :x=, :y=
protected :a, :b


tom sawyer, aka transami
transami@transami.net

                               .''.
   .''.      .        *''*    :_\/_:     .
  :_\/_:   _\(/_  .:.*_\/_*   : /\ :  .'.:.'.

.‘’.: /\ : ./)\ ‘:’* /\ * : ‘…’. -=:o:=-
:/:‘.:::. | ’ ‘’ * ‘.'/.’ (/’.‘:’.’
: /\ : ::::: = / -= o =- /)\ ’ *
‘…’ ‘:::’ === * /\ * .‘/.'. ‘._____
* | : |. |’ .—"|
* | _ .–’| || | _| |
* | .-‘| __ | | | || |
.-----. | |’ | || | | | | | || |
__’ ’ /“\ | '-.”". ‘-’ ‘-.’ '` |.

Hi –

That would not happen if accessors were, say, protected by default. But
then you’d have to ‘publicize’ them anyway, and the situation wouldn’t
be that different from the current one.

OTOH if instance variables were private (not accessible by subclasses)
all this would be much more relevant. I really felt that this was
The Right Thing but matz doesn’t [55201]. I think the main point was
that inheritance is anyway a very strong relationship, so this apparent
breach in data hiding is not that important.

that’s it! that’s it! i’ve been pulling my hair out since the beginning of my
rubyist days deciding when it is the Right Thing to use @var vs. self.var.
And finally it has become clear! the answer is simple: NEVER USE @ OUTSIDE A
GETTER OR SETTER METHOD. what, you say? indeed! in fact, with use of the

Then take into account that this goes against matz’s word [55201], for
if @var were never to be used, it would not exist in the language and
instance vars. would be class-local by default.
I have to ponder about this some more, but I have the feeling @iv is
needed sometimes.

ruby-1.6.8$ grep “[1]+@[A-Za-z_]+ ?= ?”
find . -name '*.rb' | wc -l
1026

:slight_smile:

In fact, I tend to think the attr_* shortcuts, while very useful,
sometimes lead to the impression that there’s a closer connection
between attribute accessor methods and instance variables than there
really is. The presence of such methods, and the use of instance
variables, can vary independently.

For example:

class A
def some_attribute
100
end
end

or

class B
def some_attribute
@var
end
end

or

class C
attr_reader :some_attribute
def some_attribute=(x)
@some_attribute = x * 10
end
end

and so on.

David

···

On Sat, 11 Jan 2003, Mauricio [iso-8859-1] Fernández wrote:

On Fri, Jan 10, 2003 at 08:38:50AM +0900, Tom Sawyer wrote:

On Thursday 09 January 2003 03:57 pm, Mauricio Fernández wrote:


David Alan Black
home: dblack@candle.superlink.net
work: blackdav@shu.edu
Web: http://pirate.shu.edu/~blackdav


  1. [:space:] ↩︎

its not that it is not used but only that is solely used within setter and
getter methods. in such case they might as well be class local (freeing up
more namespace). it works perfectly fine. i’ve used the principle some, the
only reason i am not using it more now is that i am writing a speed sensitive
web app and every little bit helps. using @s are a touch faster and more
efficient, but that is merely due to the design of Ruby.

it is actualy very good code practice NOT to use @ within your code, in this
way your code is much more extensible, and types can be truly enforced, etc.,
etc.

···

On Friday 10 January 2003 10:42 am, Mauricio Fernández wrote:

Then take into account that this goes against matz’s word [55201], for
if @var were never to be used, it would not exist in the language and
instance vars. would be class-local by default.
I have to ponder about this some more, but I have the feeling @iv is
needed sometimes.


tom sawyer, aka transami
transami@transami.net

                               .''.
   .''.      .        *''*    :_\/_:     .
  :_\/_:   _\(/_  .:.*_\/_*   : /\ :  .'.:.'.

.‘’.: /\ : ./)\ ‘:’* /\ * : ‘…’. -=:o:=-
:/:‘.:::. | ’ ‘’ * ‘.'/.’ (/’.‘:’.’
: /\ : ::::: = / -= o =- /)\ ’ *
‘…’ ‘:::’ === * /\ * .‘/.'. ‘._____
* | : |. |’ .—"|
* | _ .–’| || | _| |
* | .-‘| __ | | | || |
.-----. | |’ | || | | | | | || |
__’ ’ /“\ | '-.”". ‘-’ ‘-.’ '` |.