cloning an Observable

J

Josef Garvi

I have trouble cloning a descendant of Observable.

I would like to make a deep copy, so I've overridden the clone() method so
that it clones all fields correctly.

However, my new clone gets the same observer connections as the original.
What is worse, if I try to disconnect the observers from my clone by
writing something like:

protected Object clone() throws CloneNotSupportedException {
MyObject cl = (MyObject)super.clone();
System.out.println("Observers before: " + countObservers());
cl.deleteObservers();
System.out.println("Observers after: " + countObservers());
return cl;
}

(the two println commands display the number of observers connected to my
*original* object)

....I lose all the connections from my Observers to my original object as
well. in other words, the cloned object does not seem to be capable of
holding an observer list of its own....?
Any way to get around this?

TIA

--
Josef Garvi

"Reversing desertification through drought tolerant trees"
http://www.eden-foundation.org/

new income - better environment - more food - less poverty
 
J

John C. Bollinger

Josef said:
I have trouble cloning a descendant of Observable.

I would like to make a deep copy, so I've overridden the clone() method
so that it clones all fields correctly.

Apparently not. Or alternatively, perhaps you prefer an unusual
definition of "correctly."
However, my new clone gets the same observer connections as the original.
What is worse, if I try to disconnect the observers from my clone by
writing something like:

protected Object clone() throws CloneNotSupportedException {
MyObject cl = (MyObject)super.clone();
System.out.println("Observers before: " + countObservers());
cl.deleteObservers();
System.out.println("Observers after: " + countObservers());
return cl;
}

(the two println commands display the number of observers connected to
my *original* object)

...I lose all the connections from my Observers to my original object as
well. in other words, the cloned object does not seem to be capable of
holding an observer list of its own....?

Your clone is sharing its observer list with the original. This is
happening because during the cloning process, the reference to this
object was copied from the original into the clone. Instead you want
the clone to get its own object.
Any way to get around this?

Your clone() method is wrong. Without studying the matter, I cannot say
for certain whether it is even possible to write a correct one in a case
such as this. Considering that you do not want the clone to receive the
observers of the original, it may be that you are pursuing a suboptimal
strategy in the first place -- if you explain the bigger picture then
you might get some apropos suggestions.


John Bollinger
(e-mail address removed)
 
J

Josef Garvi

John C. Bollinger wrote:

Apparently not. Or alternatively, perhaps you prefer an unusual
definition of "correctly."

You're right - apparently not. I meant that the fields that *I* have added
to the Observable in my subclass are copied correctly. The problem is that
the fields in Observable, my ancestor, do not deep copy....

Your clone is sharing its observer list with the original. This is
happening because during the cloning process, the reference to this
object was copied from the original into the clone. Instead you want
the clone to get its own object.

Yep, that's precisely my goal.

Your clone() method is wrong. Without studying the matter, I cannot say
for certain whether it is even possible to write a correct one in a case
such as this.

See bottom for a simple, compilable example.

Considering that you do not want the clone to receive the
observers of the original, it may be that you are pursuing a suboptimal
strategy in the first place -- if you explain the bigger picture then
you might get some apropos suggestions.

I have a class that draws a complex view onto a frame, scaling it according
to the size of the frame. I also want to print this view, but then need to
modify a couple of settings in it. I could change the settings back and
forth in my view, but that would cause the frame to look funny for a
second. I could also implement an echo switch that i turn off when changing
the settings for the printout and turn on when I've reset the settings...
But what seemed like the neatest solution to me was to clone the view,
adjust the settings in my clone, print it and discard it.




public class DeepCopyTest extends Observable implements Cloneable {

// dummy observer class.
static class TestObserver implements Observer {
public void update(Observable arg0, Object arg1) {
// do something....
}
}

/* Create an object, connect an observer and clone it. */
public static void main(String[] args) {
TestObserver observer = new DeepCopyTest.TestObserver();
DeepCopyTest original = new DeepCopyTest();
original.addObserver(observer);
System.out.println("Observers on original before clone: "
+ original.countObservers());
try {
DeepCopyTest clone = (DeepCopyTest)original.clone();
} catch (CloneNotSupportedException e) {
// doesn't matter, it suports cloneable.
e.printStackTrace();
}
System.out.println("Observers on original after clone: "
+ original.countObservers());
}

public DeepCopyTest() {
super();
}

protected Object clone() throws CloneNotSupportedException {
DeepCopyTest cl = (DeepCopyTest)super.clone();
cl.deleteObservers(); /* the clone should not have any
observers connected to it */
return cl;
}

}


--
Josef Garvi

"Reversing desertification through drought tolerant trees"
http://www.eden-foundation.org/

new income - better environment - more food - less poverty
 
J

Josef Garvi

Josef said:
Yep, that's precisely my goal.

I figured out a way of solving it. I duplicated the code for the Observable
class (naming it CloneableObservable), and added the following clone()
method to it:

protected Object clone() throws CloneNotSupportedException {
CloneableObservable co = (CloneableObservable)super.clone();
co.obs = (Vector)obs.clone();
return co;
}

Now it gets it's own observer list, and everything works fine.

Does doing this violate Sun's license in any way?


--
Josef Garvi

"Reversing desertification through drought tolerant trees"
http://www.eden-foundation.org/

new income - better environment - more food - less poverty
 
P

P.Hill

Josef Garvi wrote:
[...]
I figured out a way of solving it. I duplicated the code for the
Observable class (naming it CloneableObservable), and added the
following clone() method to it:

protected Object clone() throws CloneNotSupportedException {
CloneableObservable co = (CloneableObservable)super.clone();
co.obs = (Vector)obs.clone();
return co;
}

Why couldn't you just subclass Obeservable to create CloneableObservable
which contains the better clone() method with the clone of the obs vector?

-Paul
 
J

Josef Garvi

P.Hill said:
Josef Garvi wrote:
[...]

Why couldn't you just subclass Obeservable to create CloneableObservable
which contains the better clone() method with the clone of the obs vector?

Because the obs field is private.... :-(

But I did actually subclass it AND paste the original code (plus my added
method) into the subclass. That way, it still connects to the interface
Observer... :)

--
Josef Garvi

"Reversing desertification through drought tolerant trees"
http://www.eden-foundation.org/

new income - better environment - more food - less poverty
 
J

John C. Bollinger

Josef said:
I figured out a way of solving it. I duplicated the code for the
Observable class (naming it CloneableObservable), and added the
following clone() method to it:

protected Object clone() throws CloneNotSupportedException {
CloneableObservable co = (CloneableObservable)super.clone();
co.obs = (Vector)obs.clone();
return co;
}

Now it gets it's own observer list, and everything works fine.

That'll do it.
Does doing this violate Sun's license in any way?

I am not a lawyer. If you plan to distribute this software or use it
other than for personal, non-commercial purposes, then I suggest you
carefully read the license that accompanies the JDK from which you
excerpted the source to judge for yourself. (Personal, non-commercial
uses potentially run afoul of licensing restrictions too, but they are
much less likely to land you in the middle of a lawsuit.) The source
file in question may also bear copyright / licensing information.

A safer path is to implement your own version of Observable from
scratch. It's not that hard. Just don't refer to the Sun source code
while you do, or you may end up right back where you started.
 

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
473,744
Messages
2,569,483
Members
44,903
Latest member
orderPeak8CBDGummies

Latest Threads

Top