[comp.lang.smalltalk] Data-Hiding? Really??

yon@apollo.HP.COM (David Yon) (01/16/90)

	One of the supposed strong points of Smalltalk and
Object-Oriented programming is the enforcement of Data-Hiding
and Encapsulation. That is to say, only an Object can access
and modify it's own instance variables.

	On the other hand, this is not entirely true.  Say
for example we have two object classes:  Apple, and AppleBasket.
AppleBasket has one instance variable called "theApple", and
Apple has an instance variable called "howRipe".  AppleBasket
has the following methods:

getApple
	"Answer the Apple in the Basket"

	^theApple.

---
putApple: anApple
	"Set the Apple in the Basket"

	theApple := anApple.

---

	Apple has the following methods:

setRipeness: anInteger
	"Set the Ripeness of the Apple"

	howRipe := anInteger.

---
getRipeness
	"Answer the Ripeness of the Apple"

	^howRipe.

---

	Now, if you evaluate the following:

| apple basket integer anotherApple |

	apple := Apple new.
	apple setRipeness: 6.
	basket := AppleBasket new.
	basket putApple: apple.
	anotherApple := basket getApple.
	anotherApple setRipeness: 5
	basket inspect.

---
	You'll find that by setting the ripeness factor of the 
anotherApple variable, it changed the state of the object in the
AppleBasket.  So the ripeness of the Apple in the AppleBasket will
have been changed to five.  On the surface, this appears to violate
the rule that only objects can change their own state.

	Any thoughts on this?

David Yon

PS: this is not a flame on Smalltalk, I happen to LOVE working in
the environment.  This is just an anomoly I hadn't thought of before.

fchan@vlsi.waterloo.edu (Francis Chan) (01/17/90)

In article <4811d5e9.20b6d@apollo.HP.COM> yon@apollo.HP.COM (David Yon) writes:
>
>	apple := Apple new.
>	apple setRipeness: 6.
>	basket := AppleBasket new.
>	basket putApple: apple.
>	anotherApple := basket getApple.
>	anotherApple setRipeness: 5
>	basket inspect.
>
>---
>	You'll find that by setting the ripeness factor of the 
>anotherApple variable, it changed the state of the object in the
>AppleBasket.  So the ripeness of the Apple in the AppleBasket will
>have been changed to five.  On the surface, this appears to violate
>the rule that only objects can change their own state.
>
>	Any thoughts on this?
>
>David Yon

I don't think its a problem. The anotherApple happens to be the "same"
apple as the apple with ripeness of 6. You got that apple from the basket
and (with a wave of the proverbial magic mouse) regressed its ripeness to 5
and then put it back into the basket (that's because the getApple method
does not remove it from the basket). In order to get "another" apple, the
getApple method should give you a copy of the apple of ripeness 6 i.e.

getApple
	"Answer the Apple in the Basket"

	^theApple copy
                  ----

Anyway the apple example probably does not show what you were trying to point
to out, I think. Yes, encapsulation does work ... but the setRipeness:
method allows direct access from the outside to the instance variable
(howRipe). Thus the onus is on the designer of the object to make sure that
what needs to be hidden remains so. For the apple example, you could take
out direct access to instance variable by removing the setRipeness: method
and adding the following methods:

"Apple class method"

new
   ^super new initialize

"Apple methods"

initialize
   howRipe := 1 "or whatever.."

ripen
  howRipe := howRipe + 1

This way you can only ripen the apple or get the apple of the same
ripeness (which you can then ripen).

Francis Chan

adamsf@turing.cs.rpi.edu (Frank Adams) (01/18/90)

In article <4811d5e9.20b6d@apollo.HP.COM> yon@apollo.HP.COM (David Yon) writes:
>	You'll find that by setting the ripeness factor of the 
>anotherApple variable, it changed the state of the object in the
>AppleBasket.  So the ripeness of the Apple in the AppleBasket will
>have been changed to five.  On the surface, this appears to violate
>the rule that only objects can change their own state.

You're confusing variables and objects.  When you get the Apple and assign
it to anotherApple, you aren't creating a new Apple object.  You are making
anotherApple be the *same* Apple object as is in the collection.  Naturally,
whatever you do it will be visible however you get access to it.

rad@aragorn.cm.deakin.oz.au (Robert Alan Dew) (01/18/90)

In article <4811d5e9.20b6d@apollo.HP.COM> yon@apollo.HP.COM (David Yon) writes:

	[ ... ]

#| apple basket integer anotherApple |
#
#	apple := Apple new.
#	apple setRipeness: 6.
#	basket := AppleBasket new.
#	basket putApple: apple.
#	anotherApple := basket getApple.
#	anotherApple setRipeness: 5
#	basket inspect.
#
#	You'll find that by setting the ripeness factor of the 
#anotherApple variable, it changed the state of the object in the
#AppleBasket.  So the ripeness of the Apple in the AppleBasket will
#have been changed to five.  On the surface, this appears to violate
#the rule that only objects can change their own state.
#
#	Any thoughts on this?

The expression basket getApple returns the Apple instance with ripeness
of 6, not another Apple instance.

Hence the object anotherApple is the object apple.

Robert Dew                             rad@aragorn.cm.deakin.oz.au
Department of Computing and Mathematics
Deakin University
Geelong 
Victoria
Australia 3217