Velocity Reviews - Computer Hardware Reviews

Velocity Reviews > Newsgroups > Programming > Java > How to "force" my object never been changed by other other objectsusing it?

Reply
Thread Tools

How to "force" my object never been changed by other other objectsusing it?

 
 
Chris Dollin
Guest
Posts: n/a
 
      02-08-2007
www wrote:

> I have a class, Data.java. Once an object of this class is created,
> several other kind objects will use it. For example:
>
> Data myDataObj = new Data(...//params);
>
> UserA userA = new UserA(myDataObj); //pass the object to another object.
> double ave = userA.getAverage();
>
> UserB userB = new UserB(myDataObj);
> ...
>
> I want myDataObj state never been modified by users.


Make all its variables private (possibly: protected) and provide
no setters. [Recurse if necessary.]

--
Chris "electric hedgehog" Dollin
"We did not have time to find out everything we wanted to know."
- James Blish, /A Clash of Cymbals/

 
Reply With Quote
 
 
 
 
www
Guest
Posts: n/a
 
      02-08-2007
Hi,

I have a class, Data.java. Once an object of this class is created,
several other kind objects will use it. For example:

Data myDataObj = new Data(...//params);

UserA userA = new UserA(myDataObj); //pass the object to another object.
double ave = userA.getAverage();

UserB userB = new UserB(myDataObj);
....


I want myDataObj state never been modified by users. Right now, I just
open my eyes widely to make sure that my code does not do it. I am
wondering if I can use some key words to enforce it, like:

final Data myDataObj = new Data(...); //my feeling this is wrong: it
just make sure the reference myDataObj (the memory address in heap being
referenced) cannot be changed. Or, the street address cannot be changed.
But the house can be modified. Am I correct?


How about ...?

public class UserA()
{
public UserA(final Data data) //constructor
{
...//code
}

}

Thank you.
 
Reply With Quote
 
 
 
 
www
Guest
Posts: n/a
 
      02-08-2007
Chris Dollin wrote:

>
> Make all its variables private (possibly: protected) and provide
> no setters. [Recurse if necessary.]
>


Sorry. My posting was not clear. I don't want Data.java completely
immutable. Occasionally, I want to change the object state, like:

dataObj.setName("bar"); //before it was "foo", now it is bar

My first posting and my purpose is: I don't want dataObj being modified
by other objects without my awareness. Such change could be burried in
UserA class' some method somewhere and I am totally not aware of it.



 
Reply With Quote
 
Chris Dollin
Guest
Posts: n/a
 
      02-08-2007
www wrote:

> Chris Dollin wrote:
>
>> Make all its variables private (possibly: protected) and provide
>> no setters. [Recurse if necessary.]

>
> Sorry. My posting was not clear. I don't want Data.java completely
> immutable. Occasionally, I want to change the object state, like:
>
> dataObj.setName("bar"); //before it was "foo", now it is bar
>
> My first posting and my purpose is: I don't want dataObj being modified
> by other objects without my awareness. Such change could be burried in
> UserA class' some method somewhere and I am totally not aware of it.


Make all its variables private (possibly: protected) and provide
setters which report the change to you (or your representative code).

If you make the setters [package] protected, and put your "safe" code
in the same package, users can't see the setter anyway.

If you don't mind the value changing, then I'm not sure why you mind
someone else changing it. But then, I don't know what your design goals
are.

--
Chris "electric hedgehog" Dollin
"A facility for quotation covers the absence of original thought." /Gaudy Night/

 
Reply With Quote
 
www
Guest
Posts: n/a
 
      02-08-2007
For another better example to show my point:

public class Car
{
final private Engine engine = new Engine(); //even the final word here
may does not serve my purpose

public void drive()
{
...//code
}

public void stop()
{
...//code
}

public void turnLeft()
{
...//code
}

...

}

I do not want Engine being completely immutable. I want to be able to
tune or fix Engine sometimes by myself. But I do NOT want when Car is
doing something(driving, stopping, or ...), Car is tuning or modifying
Engine. That is dangerous!
 
Reply With Quote
 
Oliver Wong
Guest
Posts: n/a
 
      02-08-2007

"www" <> wrote in message
news:eqffv3$smt$...
> Hi,
>
> I have a class, Data.java. Once an object of this class is created,
> several other kind objects will use it. For example:
>
> Data myDataObj = new Data(...//params);
>
> UserA userA = new UserA(myDataObj); //pass the object to another object.
> double ave = userA.getAverage();
>
> UserB userB = new UserB(myDataObj);
> ...
>
>
> I want myDataObj state never been modified by users. Right now, I just
> open my eyes widely to make sure that my code does not do it. I am
> wondering if I can use some key words to enforce it, like:
>
> final Data myDataObj = new Data(...); //my feeling this is wrong: it just
> make sure the reference myDataObj (the memory address in heap being
> referenced) cannot be changed. Or, the street address cannot be changed.
> But the house can be modified. Am I correct?


You're right that "final" won't do it. I'm assuming that you want to
make Data immutable mainly for reducing bugs, and not for security purposes.

Simply provide two interfaces for your Data object, one which provides
getters, and one which provides setters.

public interface ReadableData {
int getX();
}

public class Data implements ReadableData {
private int x;
public int getX() {
return this.x;
}

public void setX(int newValue) {
this.x = newValue;
}
}

And when you want to make your object immutable, upcast it from Data to
ReadableData:

Data myDataObj = new Data();
ReadableData immutableViewOfMyDataObj = myDataObj;
immutableViewOfMyDataObj.setX(5); /*This causes a compile error, setX() is
not defined on the interface.*/

If you have "malicious programmers" on your team, they can get around
this by downcasting from ReadableData to Data, which is why I say this only
works for bug detecting and not security. If you need something stronger
than this, then you'll probably need to make proxy classes which can read
from the original data object, but never provides a mean to write to it.

- Oliver


 
Reply With Quote
 
Oliver Wong
Guest
Posts: n/a
 
      02-08-2007

"www" <> wrote in message
news:eqfimb$tm3$...
> For another better example to show my point:
>
> public class Car
> {
> final private Engine engine = new Engine(); //even the final word here
> may does not serve my purpose
>
> public void drive()
> {
> ...//code
> }
>
> public void stop()
> {
> ...//code
> }
>
> public void turnLeft()
> {
> ...//code
> }
>
> ...
>
> }
>
> I do not want Engine being completely immutable. I want to be able to tune
> or fix Engine sometimes by myself. But I do NOT want when Car is doing
> something(driving, stopping, or ...), Car is tuning or modifying Engine.
> That is dangerous!


With this new information, I have a different recommendation. I had thought
you wanted to pass off an object which *you* can mutate, but no one else
could. Now it sounds like you want an object which can mutate, but only in
certain states:

public class Car {
public boolean isSafeToTune() {
return !driving && !turning;
}

public boolean isSafeToTurn() {
return !driving && ! tuning;
}

/**
* PRECONDITIONS: none
* POSTCONDITIONS: driving
*/
public void drive() {
driving = true;
}

/**
* PRECONDITIONS: none
* POSTCONDITIONS: !driving
*/
public void stop() {
driving = false;
}

/**
* PRECONDITIONS: isSafeToTurn()
* POSTCONDITIONS: turning
*/
public void turnLeft() {
if (!isSafeToTurn()) {
throw new IllegalStateException();
}
turning = true;
}

/**
* PRECONDITIONS: isSafeToTune()
* POSTCONDITIONS: car is tuned.
*/
public void tune() {
if (!isSafeToTune()) {
throw new IllegalStateException();
}
/*tune car somehow*/
}
}

Users of your class will have to read the javadocs carefully and understand
when and why they are allowed to call certain methods, and not other
methods.

- Oliver


 
Reply With Quote
 
Chris Uppal
Guest
Posts: n/a
 
      02-08-2007
www wrote:

> I want myDataObj state never been modified by users.


You can't do it with any combination of "final" flags (unless you want to make
your object completely immutable -- and even then you can't /quite/ manage it).

The closest you can come is to hand out an immutable proxy for the object
instead of the object itself. E.g.

public interface Data
{
int getWidth();
String getName();
int[] getMoreData();
}

public class RealData
implements Data
{
private int m_width;
private String m_name;
private int[] m_moreData;

public int getWidth() { return m_width; }
public String getName() { return m_name; }
public int[] getMoreData() { return m_moreData; }
public void setWidth(int width) { m_width = width; }
public void setName(String name) { m_name = name; }
public void setMoreData(int[] data) { m_moreData = data; }

public Data asImmutableData() { return new ImmutableData(); }

class ImmutableData
implements Data
{
public int getWidth() { return RealData.this.getWidth(); }
public String getName() { return RealData.this.getName(); }
public int[] getMoreData() { return
RealData.this.getMoreData().clone(); }
}
}

Note that there may be nothing to gain in making RealData public, and there may
be nothing to gain in making it implement Data and have public get/set methods.
But I've made it public here to illustrate how, even if it is public, a user of
the object returned by asImmutableData() cannot change it.

Note also the call to clone() in the immutable version of getMoreData() -- we
don't want to hand out a reference to the real array, since arrays (or
references to arrays) cannot be made immutable.


As something of an aside, I would be tempted to add asImmutableData() to the
Data interface, and make ImmutableData.asImmutableData() just
return this;
The idea is that something can pass on an immutable proxy for a possibly
mutable object to a third party by using asImmutableData() whether originally
had a reference to a RealData or an ImmutableData.


A simpler solution, and in many cases a better solution, is just not to worry
about it. If the other code changes your object then it must have been given
the relevant access permissions -- and if you've given it that then you
obviously trust it not to do anything stupid.

-- chris


 
Reply With Quote
 
Eric Sosman
Guest
Posts: n/a
 
      02-08-2007
www wrote On 02/08/07 11:21,:
> For another better example to show my point:
>
> public class Car
> {
> final private Engine engine = new Engine(); //even the final word here
> may does not serve my purpose
>
> public void drive()
> {
> ...//code
> }
>
> public void stop()
> {
> ...//code
> }
>
> public void turnLeft()
> {
> ...//code
> }
>
> ...
>
> }
>
> I do not want Engine being completely immutable. I want to be able to
> tune or fix Engine sometimes by myself. But I do NOT want when Car is
> doing something(driving, stopping, or ...), Car is tuning or modifying
> Engine. That is dangerous!


public void tuneOrFix() {
if (engineIsRunning())
throw new IllegalStateException("pphhht!");
removeSparkPlugs();
...
}

You might also want to modify some of the other methods:

public void drive() {
if (maintenanceInProgress())
throw new IllegalStateException(
"not while it's on the lift!");
if (! engineIsRunning())
start();
...
}

--

 
Reply With Quote
 
 
 
Reply

Thread Tools

Posting Rules
You may not post new threads
You may not post replies
You may not post attachments
You may not edit your posts

BB code is On
Smilies are On
[IMG] code is On
HTML code is Off
Trackbacks are On
Pingbacks are On
Refbacks are Off


Similar Threads
Thread Thread Starter Forum Replies Last Post
Re: How include a large array? Edward A. Falk C Programming 1 04-04-2013 08:07 PM
Whats the error in my program-creating overlapping GOval objectsusing GraphicsProgram student Java 7 01-22-2012 02:08 AM
You've never seen it before and you'll never see it again. Fred A Stover Computer Support 7 12-26-2007 03:33 AM
XML Schema never-never occurence of declared elements / attributes Soren Kuula XML 1 12-01-2005 01:27 PM
string routines go to never never land on unix Kevin C Programming 4 10-17-2003 06:07 PM



Advertisments
 



1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57