• Post Reply Bookmark Topic Watch Topic
  • New Topic
programming forums Java Mobile Certification Databases Caching Books Engineering Micro Controllers OS Languages Paradigms IDEs Build Tools Frameworks Application Servers Open Source This Site Careers Other all forums
this forum made possible by our volunteer staff, including ...
Marshals:
  • Campbell Ritchie
  • Liutauras Vilda
  • Bear Bibeault
  • Jeanne Boyarsky
  • Tim Cooke
Sheriffs:
  • Knute Snortum
  • Junilu Lacar
  • Devaka Cooray
Saloon Keepers:
  • Ganesh Patekar
  • Tim Moores
  • Carey Brown
  • Stephan van Hulst
  • salvin francis
Bartenders:
  • Ron McLeod
  • Frits Walraven
  • Pete Letkeman

Relationship between class invariants and encapsulation  RSS feed

 
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
I'm trying to get straight/clarify in my mind as to state of invariant vs. encapsulation in order to preserve a field from changing.  Or is there some overlap between the two, in the case of keeping a field from changing by making it private while the methods are public?

Hints/Examples, please. Thanks
 
Marshal
Posts: 60883
190
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
What do you think invariants means? It doesn't mean that fields don't vary. It means features which remains true at all times. For example, one of the invariants of a kettle is that its water content is never negative, so at all times content ≥ 0. You can only maintain that invariant if the content field is inaccessible to outside code, and all methods modifying it maintain that invariant. So, both concepts are separate, but encapsulation is necessary to preserve the invariants.
 
Campbell Ritchie
Marshal
Posts: 60883
190
 
Campbell Ritchie
Marshal
Posts: 60883
190
  • Likes 1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

A few minutes ago, I wrote:. . . features which remains true at all times. . . .

The following is a valid, but not thread‑safe, way to empty a kettle:-You will notice that an attempt to pour 20 of water out of a kettle containing 10 will cause content to become negative (line 6), which isn't allowed. Well, it is permissible because line 10 restores the invariants. Note, that method takes no precautions against amount being negative, so it isn't quite as valid as I said earlier.
 
Jake Monhan
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Thank very much for taking so much time to clarify invariant.

Looking at your replies and code, can one say:

1. Encapsulation is one of the tools that can be used to guarantee invariant?
2. Encapsulation is the best tool that can be used to guarantee invariant?
3. Invariant can be achieved independent of encapsulation?
 
Campbell Ritchie
Marshal
Posts: 60883
190
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator

Jake Monhan wrote:Thank very much for taking so much time to clarify invariant.

That's a pleasure

. . .
1. Encapsulation is one of the tools that can be used to guarantee invariant?

No. It is necessary but by no means sufficient. You need other techniques in addition.

2. Encapsulation is the best tool that can be used to guarantee invariant?

You are on sticky ground when you start going on about the “best tool”. It isn't; is it only part of the mechanism for maintaining the class' invariants.

3. Invariant can be achieved independent of encapsulation?

Yes, but if the implementation details of your object are visible to other code, you have to trust the other code being on its best behaviour. Otherwise the other code can violate your invariants.
 
Jake Monhan
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
So using your code snippet as example,

by modifying Water() to achieve encapsulation by adding getWater() { // return code} & setWater (int amount) { //this. code} and setting amount and content to private, we would have invariant, wouldn't we?
 
Campbell Ritchie
Marshal
Posts: 60883
190
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Water is intended to be a class, so I wouldn't necessarily want a setWater() method. It is possible to use the Water class to breach encapsulation and therefore to allow outside code to breach your invariants. Look:-Assuming the cool() methods are written similarly, you can be confident of maintaining the class' invariants. Similarly for pour(), as I showed you yesterday, with precautions to prevent negative arguments, or fill(). So far, so good. Let's assume we have correctly‑written toString() equals() and hashCode(), too.
Now you can be clever and get rid of the two fields, replacing them by a Water object. This is the naïve way to do it:-So you get both temperature and content in one fell swoop in the Water object. And nothing will go wrong until somebody does this sort of thing Unless the Water class has similar precautions against overheating, returning that Water object allows implementation details to leak, and allows other code to violate your class' invariants. It can also allow other code to change the state of your kettle, even within its invariants.
Challenges: I shall let you work out the fuller details of that problem and how to solve it. Also what to do if you decide you want a setWater() method.
A setWater() method is equivalent to taking a kettle, removing all the water it contains and filling it with a certain amount of water at a certain temperature. Is that what you do in real life? Or do you only hold the kettle under the tap and put as much water as you think you need in it? In which case the new water would be at Temperatures.TAP_TEMPERATURE and the old water at whatever temperature it happens to be at. Do you want to overload the constructor to take a Water parameter? That would mean you get a new Kettle with water already in it; all the kettles I have ever bought have been dry inside until I got them home and filled them. So I personally wouldn't write a setWater() method nor a constructor taking Water as a parameter. Work out whether the problem I have shown you would or wouldn't occur if you had that overloaded constructor. Work out whether plain simple setXXX and getXXX methods are the best way to write the Kettle class.
What other problems can you see about the Water class?
 
Campbell Ritchie
Marshal
Posts: 60883
190
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
The first version of the Kettle class doesn't suffer the same vulnerability as I showed you.Assuming water comes out of the tap at 10° and the kettle hasn't been boiled. . . . The temperature in line 4 is independent of the field in the Kettle object.
 
Jake Monhan
Ranch Hand
Posts: 86
1
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Wow, it will take me some time to answer your challenge while still preparing for the OCA exam. But given the following code snippet from your code,



Speaking very simplistically wouldn't the problems raised by w.setTemperature(1000); be solved by modify the if condition to if (degrees < 0 || degrees > 200) { }?
 
Campbell Ritchie
Marshal
Posts: 60883
190
  • Mark post as helpful
  • send pies
  • Quote
  • Report post to moderator
Yes, it would be a good idea to take time to study such an example, implement it yourself, and find out what can go wrong. I think you can learn as much from code which goes wrong as from code which runs beautifully and produces a “correct” result.

Jake Monhan wrote:. . . Speaking very simplistically wouldn't the problems raised by w.setTemperature(1000); be solved by modify the if condition to if (degrees < 0 || degrees > 200) { }?

I shall leave you to work out what would happen if you allowed an argument of 200 without taking extra precautions. The point I was trying to make is that we don't know whether the Water class takes such precautions; if it doesn't, then it is possible to use the Water class to heat the Kettle to a temperature of 1000°. Remember that the second version of Kettle doesn't have temperature and content fields; it has to take them from the Water field. Also remember, I was showing that version of the Kettle class as an example of bad design..
 
With a little knowledge, a cast iron skillet is non-stick and lasts a lifetime.
  • Post Reply Bookmark Topic Watch Topic
  • New Topic
Boost this thread!