![]() |
Re: How to "force" my object never been changed by other other objects using it?
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/ |
How to "force" my object never been changed by other other objectsusing it?
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. |
Re: How to "force" my object never been changed by other other objectsusing it?
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. |
Re: How to "force" my object never been changed by other other objects using it?
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/ |
Re: How to "force" my object never been changed by other other objectsusing it?
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! |
Re: How to "force" my object never been changed by other other objects using it?
"www" <www@nospam.com> wrote in message news:eqffv3$smt$1@news.nems.noaa.gov... > 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 |
Re: How to "force" my object never been changed by other other objects using it?
"www" <www@nospam.com> wrote in message news:eqfimb$tm3$1@news.nems.noaa.gov... > 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 |
Re: How to "force" my object never been changed by other other objects using it?
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 |
Re: How to "force" my object never been changed by other other objectsusing it?
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(); ... } -- Eric.Sosman@sun.com |
| All times are GMT. The time now is 08:21 PM. |
Powered by vBulletin®. Copyright ©2000 - 2013, vBulletin Solutions, Inc.
SEO by vBSEO ©2010, Crawlability, Inc.