Андрей Тюрин
Андрей Тюрин | Репутация: 0 (Без статуса) 17 июня 2015 в 21:51
Программирование на Java:

Нужна помощь. У меня не работает пример из лекции №9 

тема  внутри лекции клонирование.

Там есть 2 примера клонирования. 

Из примера видно, что примитивное поле было скопировано и далее существует независимо в исходном и клонированном объектах. Изменение одного не сказывается на другом.

А вот ссылочное поле было скопировано по ссылке, оба объекта ссылаются на один и тот же экземпляр класса Point. Поэтому изменения, происходящие с исходным объектом, сказываются на клонированном.

Этого можно избежать, если переопределить метод clone() в классе Test.

Далее приводится собственно пример того что у меня не работает. Переопределяется метеод   в классе Test переопределяется метод clone().


    public Object clone() throws CloneNotSupportedException {
        Test clone=null;
        try {
            clone=(Test) super.clone();
        } catch (CloneNotSupportedException e) {
            throw new InternalError(e.getMessage());
        }
        clone.p=(Point)this.p.clone();
        return clone;
    }  
 

на рисунке видно что NetBeans подчеркнул метод clone() для обьекта p типа Point.
При попытке откомпилировать программу пишет:

Exception in thread "main" java.lang.RuntimeException: Uncompilable source code - clone() has protected access in java.lang.Object
    at lecture9.clone2.Test.clone(Test.java:17)
    at lecture9.clone2.Test.main(Test.java:24)

Очевидно что для класса Point метод clone переопределён. Но пример вроде как должен работать судя по ллекции, а у меня не работает. 
кроме того нашол на ютубе разбор аналогичной темы https://www.youtube.com/watch?v=BI_Z8wTVFl8

попробовал повторить то что делается в этом видео результат такой же. Хотя на видео всё работает.
В чем проблемма? Подскажитье прожалуйста.
Спасибо

Теги: графика
Дмитрий Протопопов
Дмитрий Протопопов | Репутация: 10 (Без статуса) 18 июня 2015 в 01:35

Добрый день, Андрей.
Вы правы в том, что необходимо переопределить метод clone() в классе Point с  подходящим методом доступа (в данном примере подойдет только public), если вы хотите использовать его не только внутри текущего объекта класса Point.

Если вы не переопределите clone(), то это будет значить, что в строке 
clone.p=(Point)this.p.clone();
вы из объекта класса Test по ссылке типа Point пытаетесь получить доступ к защищенному методу класса Object(что и пишет вам компилятор). Защищенные методы доступны только для экземпляров классов-наследников. Хотя Test и Point напрямую наследуют классу Object, они находятся в разных ветках. Использовать метод clone() класса Object для объекта класса Test можно только в текущем же объекте класса Test(это делается в первом примере. Без переопределения метода clone() в классе Test). Для Point только в текущем объекте класса Point.

Вот рабочий вариант этого примера:

package intuit.tutor;

/**
 * Created by Talosar on 17.06.2015.
 */
public class Test implements Cloneable {
    Point p;
    int height;

    public Test(int x, int y, int z) {
        p=new Point(x, y);
        height=z;
    }

    public static void main(String s[]) {
        Test t1=new Test(1, 2, 3), t2=null;
        try {
            t2=(Test) t1.clone();
        } catch (CloneNotSupportedException e) {
            System.out.println("Some class doesn't implement Cloneable interface");
        }
        t1.p.x=-1;
        t1.height=-1;
        System.out.println("t2.p.x=" + t2.p.x + ", t2.p.y=" + t2.p.y +", t2.height=" + t2.height);
        System.out.println("t1.p.x=" + t1.p.x + ", t1.p.y=" + t1.p.y +", t1.height=" + t1.height);
    }

    protected Object clone() throws CloneNotSupportedException {
        Test clone=null;
        clone=(Test) super.clone();
        clone.p = (Point) this.p.clone();
        return clone;
    }
}

class Point implements Cloneable{
    public int x;
    public int y;

    Point(){
        super();
        x=0;
        y=0;
    }

    Point(int x, int y){
        super();
        this.x = x;
        this.y = y;
    }

    public Object clone() throws CloneNotSupportedException {
        Point clone=null;
        clone=(Point) super.clone();
        return clone;
    }
}

Будут еще вопросы - задавайте,  постараюсь вам помочь. Если что-то не удалось разъяснить  - уточняйте. 

Дмитрий Протопопов
Дмитрий Протопопов | Репутация: 10 (Без статуса) 18 июня 2015 в 02:00

К слову, второй рабочий вариант для этого примера – импортировать стандартный класс java.awt.Point. В этом случае вам не придется писать ничего своего для того, чтоб примера из лекции заработал, т.к. java.awt.Point по цепочке наследования реализует интерфейс Cloneable и переопределяет метод clone() с public модификатором доступа.