Const Iterator?

P

Patrick

I have a Vector *vectorA* of Objects of type *ClassB* composed within
*ClassA* as a private member, and i have a public *methodA* in
*ClassA* that returns an Iterator of *vectorA*.

This Iterator will allow the elements of *vectorA* to be modified.

Apart from creating a seperate copy of *vectorA*, is there any means
of enforcing the restriction that the Iterator not allow modifications
to both the elements of *vectorA* (instances of *ClassB*) and the
vector itself?

any help appreciated..

pat
 
M

Michael

Hi Patrick,

You can use the java.util.Collections class to obtain a read-only
version of your Vector:

Collection constVector =
java.util.Collections.unmodifiableCollection(vectorA);

Now when someone tries to modify this collection, he gets an
OperationNotSupportedException. Note that constVector is *not* a copy of
your original Vector, but a wrapper that prevents the Vector from being
modified.

Check out the Collections api for more details
http://java.sun.com/j2se/1.4.2/docs...#unmodifiableCollection(java.util.Collection)

Cheers,

Michael
 
C

Chris Smith

Patrick said:
This Iterator will allow the elements of *vectorA* to be modified.

Apart from creating a seperate copy of *vectorA*, is there any means
of enforcing the restriction that the Iterator not allow modifications
to both the elements of *vectorA* (instances of *ClassB*) and the
vector itself?

Preventing modifications to the vector itself is easy. You can create
an unmodifiable List adapter using the Collections.unmodifiableList
method. That will prevent inserting, deleting, or replacing elements of
the List. This does not amount to copying the list; it just provides an
interface adapter that protects the list against modification.

Preventing modification to the individual elements is less easy. If
you've stored mutable objects in the Vector in the first place, there is
no way to accomplish this. The best you can hope for is to write an
immutable version of that class as a value object, and create a new
Vector and fill it in with the immutable equivalents of your existing
objects. That *does* involve a full copy.

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
P

Patrick

Hi Michael,

Thanks for your reply. I tried your suggestion, but the Iterator will
allow the elements of *vectorA* to be modified.

Here is my implementation:

import java.util.*;
public class Main {

public static void main(String args[])
{ ClassA classA = new ClassA();
for (int i=1;i<11;i++)
{ classA.addElement(new ClassB(i));
}

Iterator it = classA.getIterator();
while (it.hasNext())
{ System.out.print(((ClassB)it.next()).getN()+" ");
}

it = classA.getIterator();
while (it.hasNext())
{ ((ClassB)it.next()).setN(9);
}

System.out.print("\n");

it = classA.getIterator();
while (it.hasNext())
{ System.out.print(((ClassB)it.next()).getN()+" ");
}
}
}

------------------------------------------------------------
import java.util.*;

public class ClassA
{ private Vector vectorA;

public ClassA()
{ vectorA = new Vector();
}

public void addElement(ClassB element)
{ vectorA.add(element);
}

public Iterator getIterator()
{ return Collections.unmodifiableCollection(vectorA).iterator();
}
}
-------------------------------------------------------------

public class ClassB
{ private int n;
public ClassB(int n)
{ this.n = n;
}

public int getN()
{ return this.n;
}

public void setN(int n)
{ this.n = n;
}
}
-------------------------------------------------------------

The output of which is

1 2 3 4 5 6 7 8 9 10
9 9 9 9 9 9 9 9 9 9

i.e. the internal, private data of ClassA is modifiable by a user of
the class.

I just want a user of the class to recieve an Iterator which only
allows them to view the objects of the vector, and prevents them from
modifying them.

any ideas?

pat
 
C

Christophe Vanfleteren

Patrick said:
Hi Michael,

Thanks for your reply. I tried your suggestion, but the Iterator will
allow the elements of *vectorA* to be modified.

Here is my implementation:
i.e. the internal, private data of ClassA is modifiable by a user of
the class.

I just want a user of the class to recieve an Iterator which only
allows them to view the objects of the vector, and prevents them from
modifying them.

any ideas?
pat

There no support in the language for such thing (making an Object
immutable).

You can declare a variable as final, so once it's given a value, it can not
be changed, but that still doesn't prevent the object it's referring to
from being modified (you just can't use the variable to start referring to
another object).

If you really need to make sure clients don't change the objects, you could
create a readonly version of your Object (without the setters), and put
those in the collection.
 
P

Patrick

Chris Smith said:
Preventing modifications to the vector itself is easy. You can create
an unmodifiable List adapter using the Collections.unmodifiableList
method. That will prevent inserting, deleting, or replacing elements of
the List. This does not amount to copying the list; it just provides an
interface adapter that protects the list against modification.

Preventing modification to the individual elements is less easy. If
you've stored mutable objects in the Vector in the first place, there is
no way to accomplish this. The best you can hope for is to write an
immutable version of that class as a value object, and create a new
Vector and fill it in with the immutable equivalents of your existing
objects. That *does* involve a full copy.

Thanks for the reply Chris,

So is there no way of me allowing a user of *ClassA* to view the
elements of the Vector (instances of *ClassB*) in a "read-only"
fashion and possibly throwing an exception if they call a method that
modifies the internal data of *ClassB*?

Copying the elements of the vector is not a option i can use.

Is there some method of requiring that any modifications to the
*ClassB* objects can only be carried out by the *ClassA* object that
they are composed within?

I would prefer not to have to modify *ClassB* to implement this.
 
J

Jim

Patrick said:
Thanks for the reply Chris,

So is there no way of me allowing a user of *ClassA* to view the
elements of the Vector (instances of *ClassB*) in a "read-only"
fashion and possibly throwing an exception if they call a method that
modifies the internal data of *ClassB*?

Copying the elements of the vector is not a option i can use.

Is there some method of requiring that any modifications to the
*ClassB* objects can only be carried out by the *ClassA* object that
they are composed within?

I would prefer not to have to modify *ClassB* to implement this.

The problem isn't with the Iterator. You are being given a reference
to the instance of *ClassB* contained by the Vector. Making "ClassB"
immutable might work, see how String is implemented. Any time that you
"modify" a *ClassB* instance, you return a new one instead.

Jim
 
C

Chris Smith

Patrick said:
So is there no way of me allowing a user of *ClassA* to view the
elements of the Vector (instances of *ClassB*) in a "read-only"
fashion and possibly throwing an exception if they call a method that
modifies the internal data of *ClassB*?

This is not even related to the use of Vector. The Vector is just a way
to get a reference to some ClassB instance. Once you've retrieved a
reference to the ClassB instance from the Vector, the Vector itself is
immaterial.

Making ClassB immutable is a different matter altogether.
Is there some method of requiring that any modifications to the
*ClassB* objects can only be carried out by the *ClassA* object that
they are composed within?

Yes, there is. If the ClassB instance is created by ClassA, then you
introduce a new class called InternalClassB, making it mutable. You
then modify the interface to ClassB so that it's immutable, and have it
wrap an InternalClassB. As follows...

public class ClassA
{
private InternalClassB internalB = new InternalClassB();
private ClassB bAdapter = new ClassB(internalB);

public void someMethod()
{
int t = internalB.getValue();
t += 17;
internalB.setValue(t);
}

public ClassB getClassB()
{
return bAdapter;
}
}

public class ClassB
{
private InternalClassB base;

public int getValue()
{
return base.getValue();
}
}

class InternalClassB
{
private int value;

public void setValue(int val)
{
this.value = val;
}

public int getValue()
{
return value;
}
}

--
www.designacourse.com
The Easiest Way to Train Anyone... Anywhere.

Chris Smith - Lead Software Developer/Technical Trainer
MindIQ Corporation
 
A

Adam Jenkins

Patrick said:
Hi Michael,

Thanks for your reply. I tried your suggestion, but the Iterator will
allow the elements of *vectorA* to be modified.

Here is my implementation:...

I'm guessing you're a C++ programmer. Java does not have an equivalent
to C++ const pointers or references, though I've often wished it did. In
C++ you can declare a function as returning a const reference or pointer
to an object, and then the compiler will not allow the object to be
modified via that reference. Java has no equivalent to that. In Java
you can declare a variable to be final, but if the variable is a
reference, there is no way to declare that what the variable points to
is final as well. In Java, if you want an unmodifiable version of your
object, you have to explicitly write an alternate interface to it which
doesn't allow changes to be made. This is what the
Collections.unmodifiableList function does for Lists. You would need to
do the same thing for the objects contained in the list if you don't
want them to be modifiable.

Adam
 

Ask a Question

Want to reply to this thread or ask your own question?

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

No members online now.

Forum statistics

Threads
474,431
Messages
2,571,677
Members
48,796
Latest member
Greg L.

Latest Threads

Top