Newbie Q: Data encapsulation with Ruby

Hi,

as a beginner in C++ I learned that one advantage of OOP over the
procedural programming is data hiding and encapsulation.

In C++ this is achieved via the public:, protected: and private:
keywords.

As I currently (try to) understand, Ruby does it somehow different.

class A
def initializer( k_a )
@a = k_a
end
end

will declare a class A with a “totally private” attribute “a”, which
only can be accessed vie get/set-combos.

Now I found (for me astonishling) two keywords:

 attr_reader:	  

and

 attr_writer:

which (seems to) totally “inifiltrate” the principle of data hiding
and encapsulation.

PLEASE!

Dont misundertstood my words as any kind of critism on Ruby !!!

I only want to express my current (mis)understanding of that what I
try to understand.

What is the secret behind attr_reader and attr_writer and how do they
support OOP?

Kind regards,
Meino

Hi –

Welcome to Ruby!

Hi,

as a beginner in C++ I learned that one advantage of OOP over the
procedural programming is data hiding and encapsulation.

In C++ this is achieved via the public:, protected: and private:
keywords.

As I currently (try to) understand, Ruby does it somehow different.

Ruby also has those keywords. The stuff you’re asking about below
isn’t instead of them, but in addition to them. (I don’t know C++, so
I’m not sure how close the correspondence is.)

class A
def initializer( k_a )

It’s just initialize (no ‘r’)

 @a = k_a

end
end

will declare a class A with a “totally private” attribute “a”, which
only can be accessed vie get/set-combos.

Actually your code is simpler than that: it just sets an instance
variable. At that point, nothing else has happened; there are no
get/set methods.

Now I found (for me astonishling) two keywords:

attr_reader:

and

attr_writer:

which (seems to) totally “inifiltrate” the principle of data hiding
and encapsulation.

(They’re actually methods, not keywords.)

PLEASE!

Dont misundertstood my words as any kind of critism on Ruby !!!

OK :slight_smile:

I only want to express my current (mis)understanding of that what I
try to understand.

What is the secret behind attr_reader and attr_writer and how do they
support OOP?

attr_reader and attr_writer basically serve the purpose of saving
keystrokes; they don’t do anything that you can’t do, at slightly
greater length, by hand.

Specifically, they automatically create some simple get/set methods
for instance variables. Once an instance variable has these methods,
it can be used in an attribute-like way. (There’s actually no
separate ‘attribute’ type or category; it’s all just methods, with
attribute-ness being essentially a stylistic component.)

Here’s an example:

class C
# define a get method for attribute a
def a
@a
end

# define a set method for attribute a
def a=(x)
  @a = x
end

end

c = C.new
c.a = 100 # set the a “attribute” (i.e., call method a= )
puts c.a # get the a attribute (i.e., call method a )

That class can be written like this instead:

class C
attr_reader :a
attr_writer :a
end

or, even more concisely:

class C
attr_accessor :a # read and write in one
end

The whole attr_* family of methods really just saves some typing.

And of course many combinations and permutations are possible… I’ve
just used some simple examples to show some of the basic operations of
attr_*.

David

···

On Sun, 17 Aug 2003, Meino Christian Cramer wrote:


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

“Meino Christian Cramer” mccramer@s.netic.de wrote in message
news:20030816.173048.74736153.mccramer@s.netic.de

Hi,

as a beginner in C++ I learned that one advantage of OOP over the
procedural programming is data hiding and encapsulation.

well yes - some advanced programmers would claim that encapsulation is
overrated - enter functional programming. Anyway it has its advantages as
long as you don’t turn it into a source code management nightmare.

In C++ this is achieved via the public:, protected: and private:
keywords.

ruby has the private keyword, but you can override it if you really want to
(and you can cast pointers in C++).

As I currently (try to) understand, Ruby does it somehow different.

class A
def initializer( k_a )
@a = k_a
end
end

will declare a class A with a “totally private” attribute “a”, which
only can be accessed vie get/set-combos.

Now I found (for me astonishling) two keywords:

attr_reader:

and

attr_writer:

These are auto-implementations of getter and setter methods - no more, no
less.
Nobody forces you to write them - and at any time you can remove them an
replace them with custom getter setter methods without affecting client
code.

Please refer to the Programming Ruby book by Thomas & Hunt - its available
online
http://www.rubycentral.com/book/

which (seems to) totally “inifiltrate” the principle of data hiding
and encapsulation.

Not at all - on the contrary Ruby never provides direct access to member
data.
What ruby does allow is for an external user to add new methods to class and
thus indirectly provide access to class. Thus data-hiding is a matter of
policy not enforcement.

The real benefit of getter setter methods is not data hiding but
abstraction:

Consider a collection class. At one point in its development cycle it has a
@count property and a linked list for data storage. Later it uses the Array
class for storage and relies on the array to do the counting.
If external users had direct access to the @count member, it would be
difficult to change. But now you can just write a new getter method for
count when replacing the array.

To take this example to functional programming: you would have a record
field storing the count value and a function get_count to extract the count
value. When the implementation changes you break the get_count function and
any other direct access to the count field. But since the code hopefully is
developed in a clean modular fashion, it is sufficient to update the
get_count method. Used in a discplined way this leads to faster development.
Actually there is a kind of data-hiding because you typically have a module
with public functions and hidden data structures.

Mikkel

dblack@superlink.net wrote:

attr_reader and attr_writer basically serve the purpose of saving

keystrokes; they don’t do anything that you can’t do, at slightly
greater length, by hand.

Specifically, they automatically create some simple get/set methods
for instance variables. Once an instance variable has these methods,
it can be used in an attribute-like way. (There’s actually no
separate ‘attribute’ type or category; it’s all just methods, with
attribute-ness being essentially a stylistic component.)

Here’s an example:

class C

define a get method for attribute a

def a
@a
end

define a set method for attribute a

def a=(x)
@a = x
end
end

c = C.new
c.a = 100 # set the a “attribute” (i.e., call method a= )
puts c.a # get the a attribute (i.e., call method a )

That class can be written like this instead:

class C
attr_reader :a
attr_writer :a
end

or, even more concisely:

class C
attr_accessor :a # read and write in one
end

The whole attr_* family of methods really just saves some typing.

And of course many combinations and permutations are possible… I’ve
just used some simple examples to show some of the basic operations of
attr_*.

I’d add that in Java, you “shouldn’t” (by OO principles), make your data
public. You should make
all your data private (or protected) and use accessors to get at that
data, like:

class Foo
{
private int bar;

public int getBar()
{ 
   return bar;
}

public void setBar(int x)
{
   bar = x;
}

}

All Ruby is doing is automating the otherwise tedious processes you need
to use in Java.
It’s not using any different principles (in fact, it enforces the
recommended principles
better).

Just an addendum, not a correction.

  • Dan

P.S.: It’s also the case that people can add methods to your class to
access private data
you don’t want them to. That’s just a part of ruby. I believe the
#freeze method prevents
that, though.

Hi David,

(…)

PLEASE!

Dont misundertstood my words as any kind of critism on Ruby !!!

OK :slight_smile:

:O)

I only want to express my current (mis)understanding of that what I
try to understand.

What is the secret behind attr_reader and attr_writer and how do they
support OOP?

attr_reader and attr_writer basically serve the purpose of saving
keystrokes; they don’t do anything that you can’t do, at slightly
greater length, by hand.

Yes…
But…did I understood so far:
“Setting” an attribute with “attr_accessor” means it is world
readable and writeable (or speaking the UNIX-way, it is
rw-rw-rw :wink: ?

I understand fully that I am neither urged by the ruby community to give them fully access to my private data nor that there is no other destiny in ruby for a variables life than to be of publicc access...

…but I only want to try to express what I am currently think of
haveing understood…(and to struggle with my limited English…)

X-)

Specifically, they automatically create some simple get/set methods
for instance variables. Once an instance variable has these methods,
it can be used in an attribute-like way. (There’s actually no
separate ‘attribute’ type or category; it’s all just methods, with
attribute-ness being essentially a stylistic component.)

HU?

Until this point I thought, “attributes” are instance variables…
(haveing C++ in mind…)

Here’s an example:

class C
# define a get method for attribute a
def a
@a
end

# define a set method for attribute a
def a=(x)
  @a = x
end

end

c = C.new
c.a = 100 # set the a “attribute” (i.e., call method a= )
puts c.a # get the a attribute (i.e., call method a )

That class can be written like this instead:

class C
attr_reader :a
attr_writer :a
end

or, even more concisely:

class C
attr_accessor :a # read and write in one
end

The whole attr_* family of methods really just saves some typing.

…but for me it would break down all “walls” and access controls a
class would (should?) have over its instance variables…

Doesn’t such a design tend to become more “procedural” (in opposite
to OOP) than wanted?

(again, no critism, just a question of a newbie…)

And of course many combinations and permutations are possible… I’ve
just used some simple examples to show some of the basic operations of
attr_*.

Thank you very much for your help David ! :O)

David


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

Oh! an OOP-Url: It declares your “shoe” as “private” (“u” sounds in german
as the “oe” of “shoe” in English… :wink: ::)))

Only kidding…
Keep hacking!
Meino

···

From: dblack@superlink.net
Subject: Re: Newbie Q: Data encapsulation with Ruby
Date: Sun, 17 Aug 2003 00:50:56 +0900

They can also use instance_eval, or add singleton methods to the object.
Now, if you cannot trust the people you’re working with not to break
your design you’re screwed, no matter the language or the technology.

···

On Sun, Aug 17, 2003 at 01:02:45AM +0900, Dan Doel wrote:

P.S.: It’s also the case that people can add methods to your class to
access private data
you don’t want them to. That’s just a part of ruby. I believe the
#freeze method prevents
that, though.


_ _

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

We all know Linux is great… it does infinite loops in 5 seconds.
- Linus Torvalds about the superiority of Linux on the Amterdam Linux Symposium

Hi Dan,

The whole attr_* family of methods really just saves some typing.

And of course many combinations and permutations are possible… I’ve
just used some simple examples to show some of the basic operations of
attr_*.

I’d add that in Java, you “shouldn’t” (by OO principles), make your data
public. You should make
all your data private (or protected) and use accessors to get at that
data, like:

That is exactly what I thought…

class Foo
{
private int bar;

public int getBar()
{ 
   return bar;
}

public void setBar(int x)
{
   bar = x;
}

}

All Ruby is doing is automating the otherwise tedious processes you need
to use in Java.

(in general)…but with the getter/setter (especially setter) you
gain more control over what is going in and out.

A setter could control the validity of the value range…

(I am not saying, that it is NOT POSSIBLE in ruby to write
setter/getter methods! This is a more general remark on OOP…)

It’s not using any different principles (in fact, it enforces the
recommended principles
better).

Just an addendum, not a correction.

  • Dan

P.S.: It’s also the case that people can add methods to your class to
access private data
you don’t want them to. That’s just a part of ruby. I believe the
#freeze method prevents
that, though.

Keep hacking!
Meino

···

From: Dan Doel djd15@po.cwru.edu
Subject: Re: Newbie Q: Data encapsulation with Ruby
Date: Sun, 17 Aug 2003 01:02:45 +0900

Hi –

From: dblack@superlink.net

attr_reader and attr_writer basically serve the purpose of saving
keystrokes; they don’t do anything that you can’t do, at slightly
greater length, by hand.

Yes…
But…did I understood so far:
“Setting” an attribute with “attr_accessor” means it is world
readable and writeable (or speaking the UNIX-way, it is
rw-rw-rw :wink: ?

You’re not setting it with attr_accessor; you’re using attr_accessor
to automatically create two methods for you. One reads an instance
variable, the other sets it. If you don’t want those operations to
be possible, then you wouldn’t want to create those methods.

Specifically, they automatically create some simple get/set methods
for instance variables. Once an instance variable has these methods,
it can be used in an attribute-like way. (There’s actually no
separate ‘attribute’ type or category; it’s all just methods, with
attribute-ness being essentially a stylistic component.)

HU?

Until this point I thought, “attributes” are instance variables…
(haveing C++ in mind…)

I had Ruby in mind :slight_smile: Didn’t mean it to apply to all languages. I
don’t know C++, so I can’t make a detailed comparison, but in Ruby,
when you send a message to an object – say, obj.a – it always means
that you are asking the object to execute the method corresponding to
the message. There’s no separate concept of “retrieving an
attribute”, at least not at the language level. It’s conventional to
use instance variables to bring about attribute-like functionality.
But you can use instance variables for other things, and you can do
things behind the scenes in your setter and getter methods that don’t
involve instance variables.

A simple example of some things you can do:

class C
def state=(s) # as in United States :slight_smile:
raise ArgumentError unless %w{ AR AZ CA DE }.include?(s.upcase)
@st = s.upcase
end

def state
  @st.dup      # solving the problem I mentioned earlier
end

end

c = C.new

c.state = “Delaware” # error

c.state = “dE”
p c.state # “DE”

(Using @st instead of @state is pointless, except to illustrate that
your get/set methods don’t actually have to have the same names as
any instance variables you use to implement them. )

David

···

On Sun, 17 Aug 2003, Meino Christian Cramer wrote:


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

Hi, Meino…

I’ll make some comments. Maybe we can make things
more clear.

Yes…
But…did I understood so far:
“Setting” an attribute with “attr_accessor” means it is world
readable and writeable (or speaking the UNIX-way, it is
rw-rw-rw :wink: ?

First of all, understand that an instance variable is
simply a variable. It starts with an @ sign and is
scoped within the instance methods.

The “setter” and “getter” are methods, and they are
entirely optional. You define them ONLY when you want
the outside world to access the variable this way.

Inside your class, you can use any number of instance
variables that are not accessible to the outside world
at all.

Also note that, in Ruby: private, public, and protected
apply strictly to methods. They have nothing to do with
instance variables, which are always private.

I hope this does not confuse you further, but I will
say this also… You understand now how the attr_*
methods work, I think. But remember that this is only
a shorthand. You can create methods of any name “by
hand” – and the names do NOT have to match instance
variables at all. You could (though it would be silly)
create methods that “look” like readers and writers,
but do nothing of the sort:

class C
def initialize(val)
@foo = val # Here’s an instance var
@bar = “some value” # Here’s another (totally
# invisible to outside world)
end
def foo
puts “I’m a stupid method pretending to be a getter.”
end
def foo=(x)
puts “I look like a setter, but I don’t even look at my parameter.”
end
end

And someone may point out that even a “hidden” instance
var can be accessed by someone trying hard enough… but
I don’t want to mention advanced things to you yet. If
you are interested, you can look at things like ‘send’ and
‘instance_eval’.

Cheers,
Hal

···

----- Original Message -----
From: “Meino Christian Cramer” mccramer@s.netic.de
To: “ruby-talk ML” ruby-talk@ruby-lang.org; dblack@superlink.net
Sent: Saturday, August 16, 2003 12:31 PM
Subject: Re: Newbie Q: Data encapsulation with Ruby

Attributes are methods which give you access to instance variables. As
others have said, they are the quivalent of Java’s getters and setters.

attr_reader :fred

is the same as writing

def fred
@fred
end

Ruby is good this way: objects can choose to expose their state
directly, but then they can change to having more complex method-based
access. The key thing is that this change is transparent to users of
the object: when you say

f.age

you have no idea if you’re getting the age as a transparent reference
to an instance variable or as the result of some computation. Read
Meyer’s Object Oriented Software Construction for a lot of information
on this - he calls it the Uniform Access Principle, and it’s one way of
increasing encapsulation and decreasing coupling.

Cheers

Dave

···

On Saturday, August 16, 2003, at 12:31 PM, Meino Christian Cramer wrote:

Until this point I thought, “attributes” are instance variables…
(haveing C++ in mind…)

Hello Meino,

I think you’re raising a question about what OOP really is,
particularly when source code is open.

There are some objects that hold information that is used by other
objects. You want these objects to provide that information when
another object asks for it. This is the method attr_reader provides.
Sometimes you want an object to permit other objects to update
information being held by that object. This is the method attr_writer
provides. You can use one or the other or both or neither. Some objects
have no methods permitting access to the information they hold – this
kind of object does something in response to a method call by another
object, but does not give or receive information that it contains.

As the programmer, you see the object from the inside and the outside.
If you use test-driven development, you start by looking at the object
from the outside and give it methods that will respond as desired when
called – you are focusing on the interface to the object. Once you
write the test you then change your (conceptual) position and go inside
the object and figure out how you can respond to the method. This often
involves using some procedural code (although you can create objects of
any available class inside the method as well).

Note that the above is all theory. There is no substitute for reading
other people’s code (check the files in your /lib/ruby/1.8/ directory)
and writing your own code. One last note, in Ruby, you don’t have to
write your own classes and methods to write a functioning program –
you can use objects defined by classes and methods built in or added to
Ruby by others and write programs entirely in the “main” object space.

Regards,

Mark

···

On Saturday, August 16, 2003, at 01:31 PM, Meino Christian Cramer wrote:

[snip]

The whole attr_* family of methods really just saves some typing.

…but for me it would break down all “walls” and access controls a
class would (should?) have over its instance variables…

Doesn’t such a design tend to become more “procedural” (in opposite
to OOP) than wanted?
[snip]

Hi –

P.S.: It’s also the case that people can add methods to your class to
access private data
you don’t want them to. That’s just a part of ruby. I believe the
#freeze method prevents
that, though.

They can also use instance_eval, or add singleton methods to the object.
Now, if you cannot trust the people you’re working with not to break
your design you’re screwed, no matter the language or the technology.

The one sort of “innocent” area where the Ruby attribute conventions
can also cause breakage is in the return values of reader methods –
those values being, of course, references:

class C
attr_accessor :s
end

c = C.new
c.s = “hello”
s = c.s
s << " there" # looks innocently local, but…
p c.s # “hello there”

One can get around this with dup’ing and/or freeze’ing, but I think it
may just be that the referential nature of Ruby variables and the
concept of an object being in charge of its own state are somewhat
in conflict.

(One can also get around this by not doing it, but for some reason it
strikes me as something that could happen inadvertently.)

David

···

On Sun, 17 Aug 2003, Mauricio [iso-8859-1] Fernández wrote:

On Sun, Aug 17, 2003 at 01:02:45AM +0900, Dan Doel wrote:


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

Meino Christian Cramer wrote:

(in general)…but with the getter/setter (especially setter) you
gain more control over what is going in and out.

A setter could control the validity of the value range…

(I am not saying, that it is NOT POSSIBLE in ruby to write
setter/getter methods! This is a more general remark on OOP…)

Okay, I see where the confusion is.

Ruby style doesn’t recommend that you write setter/getter methods with
names like:

setA/getA

Instead of setA, you write:

def a=(val)
@a = val
end

And instead of getA, you write

def a
@a
end

Basically, the private instance variable is called @var_name, the getter
is a method named
var_name, and the setter is a method named var_name=.

You can write these methods yourself, as I have above. All attr_reader
and attr_writer do
is write a default implementation (basically, the exact forms that I
wrote above), to save you
some typing. If you want, you can do:

def a=(val)
if val < 0
raise “a cannot be negative”
end

# convert from degrees to radians

a = val*pi/360

end

This is an interesting system, in that you can have one internal
variable linked to what looks like
multiple pseudo “public” variables. Like:

class Angle
# this class stores the angle in grads

def grads
   @grads
end

def grads=(val)
   @grads = val
end

def radians
   @grads*pi/400
end

def radians=(val)
   @grads = val*400/pi;
end

def degrees
   @grads*360/400
end

def degrees=(val)
   @grads = val*400/360
end

end

However, the first two methods here are just straigt setter/getters, so
you could write:

class Angle
attr_reader :grads
attr_writer :grads

end

So they’re just convenience methods.

Hope this helps.

  • Dan

Ruby is good this way: objects can choose to expose their state
directly, but then they can change to having more complex method-based
access.
[emphasis added]

Once again, Dave Thomas hits the nail on the head. The reason attr_reader
and attr_writer are OO-approved (at least, to the degree that Java getX and
setX accessors are) is because you can override their behavior later. The
same would not be true of making Java fields public, since there is no way
you can “intercept” direct field access and no way to write methods that
look like direct field access. (I think the same is true in C++?)

I think the way Ruby’s instance vars and attrs work is the safest, most
convenient idiom I’ve seen for this sort of thing…

Hi –

Until this point I thought, “attributes” are instance variables…
(haveing C++ in mind…)

Attributes are methods which give you access to instance variables. As
others have said, they are the quivalent of Java’s getters and setters.

attr_reader :fred

is the same as writing

def fred
@fred
end

Ruby is good this way: objects can choose to expose their state
directly, but then they can change to having more complex method-based
access. The key thing is that this change is transparent to users of
the object: when you say

f.age

you have no idea if you’re getting the age as a transparent reference
to an instance variable or as the result of some computation. Read
Meyer’s Object Oriented Software Construction for a lot of information
on this - he calls it the Uniform Access Principle, and it’s one way of
increasing encapsulation and decreasing coupling.

I’m finding this thread interesting enough that I shall risk (a)
hair-splittage; and (b) revelation of ignorance, in order to take it
further.

What I’m now getting curious about is the use, utility, and stability
of the whole notion of an ‘attribute’ in Ruby. It seems like there’s
no such thing as saying, from the outside (i.e., from the perspective
of someone using the class), “This object has a ‘blah’ attribute” –
which I think is essentially the Uniform Access Principle in action,
but it goes further because even when something is (as close as we get
to) an attribute, it’s still just a method that happens to return an
instance variable. Even from the class writer’s perspective, it’s not
qualitatively different from writing any other method (the way, say,
using global variables feels qualitatively different from using local
variables).

This is what I was groping at in saying earlier that there’s no
separate category of ‘attribute’ at the language level; it’s woven
from the same cloth, so to speak, as all the code around it, but
happens to fulfill a kind of attribute-like function. Or is that too
mushy a way of looking at it?

I find this all interesting in part because it’s something I keep
seeing in Ruby: incredibly simple, consistent, homogenous language
design from which one can – but does not have to – build and name
constructs which resemble those in other OO languages (all those ones
I don’t know :slight_smile: My favorite example is class methods, and the fact
that they are essentially singleton methods added to Class objects by
the same mechanism that singleton methods are added to any other
object – and that what gives them special-citizen status is that the
concept of a class method exists already and has some proven utility.

It seems to me that if some day everyone decides that ‘attribute’ is a
superfluous category, or that class methods shouldn’t be looked at as
different from other singleton methods – or if new concepts at that
level of abstraction come into being – Ruby will be incredibly
ready, because these things can just sort of flow out of, and melt
back into, the language…

David

···

On Sun, 17 Aug 2003, Dave Thomas wrote:

On Saturday, August 16, 2003, at 12:31 PM, Meino Christian Cramer wrote:


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

Hi David,

Hi –

P.S.: It’s also the case that people can add methods to your class to
access private data
you don’t want them to. That’s just a part of ruby. I believe the
#freeze method prevents
that, though.

They can also use instance_eval, or add singleton methods to the object.
Now, if you cannot trust the people you’re working with not to break
your design you’re screwed, no matter the language or the technology.

The one sort of “innocent” area where the Ruby attribute conventions
can also cause breakage is in the return values of reader methods –
those values being, of course, references:

class C
attr_accessor :s
end

c = C.new
c.s = “hello”
s = c.s
s << " there" # looks innocently local, but…
p c.s # “hello there”

One can get around this with dup’ing and/or freeze’ing, but I think it
may just be that the referential nature of Ruby variables and the
concept of an object being in charge of its own state are somewhat
in conflict.

Ooopps…the newbie’s nightmare becomes reality.

I tend to say, that this side effect is not what I would have
exspected…

My innocent (newbie) knowledge may be the reason for it…

(One can also get around this by not doing it, but for some reason it
strikes me as something that could happen inadvertently.)

David


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

Keep Hacking!
Meino

···

From: dblack@superlink.net
Subject: Re: Newbie Q: Data encapsulation with Ruby
Date: Sun, 17 Aug 2003 01:28:22 +0900

On Sun, 17 Aug 2003, Mauricio [iso-8859-1] Fernández wrote:

On Sun, Aug 17, 2003 at 01:02:45AM +0900, Dan Doel wrote:

Hi –

Ruby is good this way: objects can choose to expose their state
directly, but then they can change to having more complex method-based
access.
[emphasis added]

Once again, Dave Thomas hits the nail on the head. The reason attr_reader
and attr_writer are OO-approved (at least, to the degree that Java getX and
setX accessors are) is because you can override their behavior later. The
same would not be true of making Java fields public, since there is no way
you can “intercept” direct field access and no way to write methods that
look like direct field access. (I think the same is true in C++?)

Ruby also has the #private method (referred to wrongly by me, earlier,
as a keyword), so you could do for example:

class C
attr_reader :a
private
attr_writer :a
def something
# you can use #a= here
end
end

C.new.a = 1 # error – private method called

In other words, you can layer access levels on top of the
attr_*-generated methods (and others, of course).

David

···

On Sun, 17 Aug 2003, Joe Cheng wrote:


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

dblack@superlink.net wrote:

I’m finding this thread interesting enough that I shall risk (a)
hair-splittage; and (b) revelation of ignorance, in order to take it
further.

What I’m now getting curious about is the use, utility, and stability
of the whole notion of an ‘attribute’ in Ruby. It seems like there’s
no such thing as saying, from the outside (i.e., from the perspective
of someone using the class), “This object has a ‘blah’ attribute” –
which I think is essentially the Uniform Access Principle in action,
but it goes further because even when something is (as close as we get
to) an attribute, it’s still just a method that happens to return an
instance variable. Even from the class writer’s perspective, it’s not
qualitatively different from writing any other method (the way, say,
using global variables feels qualitatively different from using local
variables).

This is what I was groping at in saying earlier that there’s no
separate category of ‘attribute’ at the language level; it’s woven
from the same cloth, so to speak, as all the code around it, but
happens to fulfill a kind of attribute-like function. Or is that too
mushy a way of looking at it?

I don’t think it’s ‘too mushy.’ One could argue that Ruby’s flexibility
in moving between the method and attribute concept is a feature and only
causes confusion when one is coming from a background where the
distinction is forced.

I find this all interesting in part because it’s something I keep
seeing in Ruby: incredibly simple, consistent, homogenous language
design from which one can – but does not have to – build and name
constructs which resemble those in other OO languages (all those ones
I don’t know :slight_smile: My favorite example is class methods, and the fact
that they are essentially singleton methods added to Class objects by
the same mechanism that singleton methods are added to any other
object – and that what gives them special-citizen status is that the
concept of a class method exists already and has some proven utility.

It seems to me that if some day everyone decides that ‘attribute’ is a
superfluous category, or that class methods shouldn’t be looked at as
different from other singleton methods – or if new concepts at that
level of abstraction come into being – Ruby will be incredibly
ready, because these things can just sort of flow out of, and melt
back into, the language…

David

Well said David. As an example I find that the Ruby syntax like this
allows me to move from skeleton code to more richly featured code more
easily:

some_obj.connection.send( data )

When I first write the class of some_obj it might have one ‘connection’
and that is indeed the varible ‘connection.’ Later I come back and
rewrite the class to contain multiple connections and then make
‘connection’ a method that picks the best connection (or whatever).
This is a big time saver for me that works even if I didn’t see it coming.

Michael Garriss

Meino Christian Cramer wrote:

Ooopps…the newbie’s nightmare becomes reality.

I tend to say, that this side effect is not what I would have
exspected…

My innocent (newbie) knowledge may be the reason for it…

Well, I think the big reason for the above problem in this case is that
Ruby Strings aren’t
immutable like they are in Java. You could have the same problem in C++:

class Foo
{
string var;

public:
string & getVar();
void setVar(const string & s);
};

Foo foo;

foo.setVar(“blarg”);

string s = foo.getVar();
s[0] = ‘f’;
cout << foo.getVar(); // prints “flarg”

The difference in C++ is that reference types must be explicitly
declared. You’d have
the same problem in Java with mutable objects, though.

class IntWrapper {
private int value;

public IntWrapper(int v) { value = v; }
public void setValue(int i) {value = i; }
public int getValue() { return value; }

}

class Example {
private IntWrapper integer;

public Example() { integer = new IntWrapper(33); }

public IntWrapper getInteger() { return integer; }
public String toString() { return 

Integer.toString(integer.getValue()); }
}

Example e = new Example();

IntWrapper mutable = e.getInteger();
mutable.setValue(55);

System.out.println(e); // prints 55 instead of 33

So this problem is not unique to Ruby.

Note, all this code is off the top of my head, so it may contain syntax
errors. :slight_smile:

Cheers.

  • Dan

This is what I was groping at in saying earlier that there’s no
separate category of ‘attribute’ at the language level; it’s woven
from the same cloth, so to speak, as all the code around it, but
happens to fulfill a kind of attribute-like function. Or is that too
mushy a way of looking at it?

I don’t think it’s ‘too mushy.’ One could argue that Ruby’s flexibility
in moving between the method and attribute concept is a feature and only
causes confusion when one is coming from a background where the
distinction is forced.

Interesting discussion!

Just to illustrate by way of other languages, you can see the contrast in
Java vs. C#. Java “attributes” are simply methods that follow a naming
convention (getX/setX), while C# has properties which are to a certain
degree woven from a different cloth (e.g. you can reflect on a class and
just examine its properties, as distinct from its methods; and they have a
different syntax when you’re writing them). The times I have seen where it
is truly useful/necessary to distinguish properties from methods are when
you’re using code-generation or -automation (serialization and data binding,
for example) or RAD authoring tools. In the general case I’d prefer to
build methods and attributes from the same parts…