Клонирование внутренних классов
От: Oval  
Дата: 18.08.04 18:52
Оценка:
При клонировании объекта внешнего класса, если он содержит объекты внутренних классов эти объекты при клонировании ссылаются на старого предка внешнего класса.
Как сделать чтобы они ссылались на вновь созданный объект внешнего класса?
Re: Клонирование внутренних классов
От: _zer0  
Дата: 19.08.04 00:35
Оценка: 1 (1)
Здравствуйте, Oval, Вы писали:

O>При клонировании объекта внешнего класса, если он содержит объекты внутренних классов эти объекты при клонировании ссылаются на старого предка внешнего класса.

O>Как сделать чтобы они ссылались на вновь созданный объект внешнего класса?


у внешнего класса перекрываешь clone()

а внутри клонируешь внутренний и переприсваеваешь необходимые ссылки руками, что-то типа

public Object clone() throws CloneNotSupportedException {
  Parent result = (Parent) super.clone();
  Child child = result.child.clone();
  child.parent = result;
  return result;
}
Re[2]: Клонирование внутренних классов
От: dshe  
Дата: 19.08.04 06:59
Оценка: 3 (2)
Здравствуйте, _zer0, Вы писали:

_>Здравствуйте, Oval, Вы писали:


O>>При клонировании объекта внешнего класса, если он содержит объекты внутренних классов эти объекты при клонировании ссылаются на старого предка внешнего класса.


Не совсем понятна фраза "он содержит объекты внутренних классов ". Экземпляр внешнего класса ничего не знает о своих внутренних экземплярах (если, конечно, их не региситрировать явно руками). Тут связь однонаправленная -- от внутреннего к внешнему.

O>>Как сделать чтобы они ссылались на вновь созданный объект внешнего класса?


_>у внешнего класса перекрываешь clone()


_>а внутри клонируешь внутренний и переприсваеваешь необходимые ссылки руками, что-то типа


_>
_>public Object clone() throws CloneNotSupportedException {
_>  Parent result = (Parent) super.clone();
_>  Child child = result.child.clone();
_>  child.parent = result;
_>  return result;
_>}
_>


Экземпляр внутреннего класса не может поменять ссылку на свой внешний экземпляр. Полагаю, что в данном случае, наверное, придется отказаться от отношения между классами "inner-outer", а реализовать эту связь руками (с дополнительной возможностью поменять экземпляр внешнего класса)

Т.е. вместо
public class Outer {
     public class Inner {
          public Outer getOuter() {
               return Outer.this;
          }
     }
}

сделать
public class PseudoOuter {
     public static class PseudoInner {
          private PseudoOuter outer;

          public PseudoInner(PseudoOuter outer) {
               this.outer = outer;
          }

          public PseudoOuter getOuter() {
               return outer;
          }

          public void setOuter(PseudoOuter outer) {
               this.outer = value;
          }
     }
}
--
Дмитро
Re[3]: Клонирование внутренних классов
От: Oval  
Дата: 19.08.04 07:18
Оценка:
Здравствуйте, dshe, Вы писали:

D>Здравствуйте, _zer0, Вы писали:


_>>Здравствуйте, Oval, Вы писали:


O>>>При клонировании объекта внешнего класса, если он содержит объекты внутренних классов эти объекты при клонировании ссылаются на старого предка внешнего класса.


D>Не совсем понятна фраза "он содержит объекты внутренних классов ". Экземпляр внешнего класса ничего не знает о своих внутренних экземплярах (если, конечно, их не региситрировать явно руками). Тут связь однонаправленная -- от внутреннего к внешнему.


Вот сласс



class Outer
{

Inner inner;

 Outer()
 {
   inner = new Inner();
 }


class Inner
{

}
}


Он содержит объект внутренего класса и все о нем знает.(Может его создать присвоить изменить)



O>>>Как сделать чтобы они ссылались на вновь созданный объект внешнего класса?


_>>у внешнего класса перекрываешь clone()


_>>а внутри клонируешь внутренний и переприсваеваешь необходимые ссылки руками, что-то типа


_>>
_>>public Object clone() throws CloneNotSupportedException {
_>>  Parent result = (Parent) super.clone();
_>>  Child child = result.child.clone();
_>>  child.parent = result;
_>>  return result;
_>>}
_>>


D>Экземпляр внутреннего класса не может поменять ссылку на свой внешний экземпляр. Полагаю, что в данном случае, наверное, придется отказаться от отношения между классами "inner-outer", а реализовать эту связь руками (с дополнительной возможностью поменять экземпляр внешнего класса)


Вот этого то и не хотелось, но раз никак...
Re[4]: Клонирование внутренних классов
От: dshe  
Дата: 19.08.04 07:38
Оценка: 4 (1) +1
Здравствуйте, Oval, Вы писали:

O>Здравствуйте, dshe, Вы писали:



O>Вот сласс


O>


O>class Outer
O>{

O>Inner inner;

O> Outer()
O> {
O>   inner = new Inner();
O> }


O>class Inner
O>{

O>}
O>}
O>


O>Он содержит объект внутренего класса и все о нем знает.(Может его создать присвоить изменить)




O>>>>Как сделать чтобы они ссылались на вновь созданный объект внешнего класса?


D>>Экземпляр внутреннего класса не может поменять ссылку на свой внешний экземпляр. Полагаю, что в данном случае, наверное, придется отказаться от отношения между классами "inner-outer", а реализовать эту связь руками (с дополнительной возможностью поменять экземпляр внешнего класса)


O>Вот этого то и не хотелось, но раз никак...


Можно еще попробовать использовать serialization для создания глубокой копии Outer'а. Что-то типа такого:
/*
 * Created on 13.04.2004
 *
 */
package test;

import java.io.ByteArrayInputStream;
import java.io.ByteArrayOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.ObjectInputStream;
import java.io.ObjectOutputStream;
import java.io.OutputStream;
import java.io.Serializable;

/**
 * @author dshe
 *
 */
public class Outer implements Cloneable, Serializable {
    private final Inner inner;

    public Outer() {
        inner = new Inner();
    }

    public Object clone() {
        return byteArrayToObject(objectToByteArray(this));
    }

    public class Inner implements Serializable {
        public Outer getOuter() {
            return Outer.this;
        }
    }

    public Inner getInner() {
        return inner;
    }

    public static void main(String[] args) {
        Outer o = new Outer();
        Outer p = (Outer) o.clone();
        System.out.println(o != p);
        System.out.println(o.getInner() != p.getInner());
        System.out.println(o.getInner().getOuter() != p.getInner().getOuter());
        System.out.println(o == o.getInner().getOuter());
        System.out.println(p == p.getInner().getOuter());
    }

// -------

    private static byte[] objectToByteArray(Object object) {
        ByteArrayOutputStream bos = new ByteArrayOutputStream();
        ObjectOutputStream oos = null;
        try {
            oos = new ObjectOutputStream(bos);
            oos.writeObject(object);
        }
        catch(IOException exc) {
            throw new RuntimeException(exc.toString());
        }
        finally {
            closeSilently(oos);
            closeSilently(bos);
        }
        return bos.toByteArray();
    }

    private static Object byteArrayToObject(byte[] array) {
        ByteArrayInputStream bis = new ByteArrayInputStream(array);
        ObjectInputStream ois = null;
        try {
            ois = new ObjectInputStream(bis);
            return ois.readObject();
        }
        catch(IOException exc) {
            throw new RuntimeException(exc.toString());
        }
        catch(ClassNotFoundException exc) {
            throw new RuntimeException(exc.toString());
        }
        finally {
            closeSilently(ois);
            closeSilently(bis);
        }
    }

    private static void closeSilently(OutputStream os) {
        try {
            if(os != null) os.close();
        }
        catch(IOException exc) {
            // just ignore
        }
    }

    private static void closeSilently(InputStream is) {
        try {
            if(is != null) is.close();
        }
        catch(IOException exc) {
            // just ignore
        }
    }

}
--
Дмитро
 
Подождите ...
Wait...
Пока на собственное сообщение не было ответов, его можно удалить.