Java дубликат клипа - PullRequest
       15

Java дубликат клипа

1 голос
/ 26 марта 2019

Я нашел много тем, предлагающих и обсуждающих клонирование, но я не смог реализовать метод, который может дублировать мой объект Clip.

Вот что я пробовал:

// ... setting up class ...

MyClip GunClip = new MyClip();

GunClip.set(AudioSystem.getClip());

AudioInputStream inputStream = AudioSystem.getAudioInputStream(new BufferedInputStream(getClass().getResourceAsStream("/Resources/sound/Laser.wav")));

GunClip.dummy.open(inputStream);
// ...

Затем, когда событие срабатывает, я хочу воспроизвести этот звук несколько раз.Поэтому я пытаюсь продублировать его:

class MyClip implements Cloneable {

    Clip dummy;

    public MyClip() {

    }

    public Clip get() {
        return dummy;
    }

    public void set(Clip c) {
        this.dummy = c;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }

}

Я реализую класс Cloneable, как предложено в этой теме.

И затем клонирую его перед тем, как воспроизвести его:

MyClip c = (MyClip) GunClip.clone();

c.dummy.setFramePosition(0);
c.dummy.start();

Но даже сейчас это не работает ...

РЕДАКТИРОВАТЬ: я выяснил, почему это не работает, потому что это не глубокийclone и InputStream, который используется исходным GunClip, не клонируется.Но поскольку Clip является абстрактным интерфейсом, клонировать его может быть сложнее, чем обычно.

Ответы [ 2 ]

2 голосов
/ 26 марта 2019

Мне нравится писать конструктор копирования в моих объектах. Это дает мне возможность клонировать объект без применения результата. Вы можете использовать этот конструктор для чистой реализации Cloneable, и, тем не менее, ваш объект поддерживает этот интерфейс. Вот что я имею в виду, включая пример кода для клонирования вашего объекта обоими этими способами:

static class MyClip implements Cloneable {

    Clip dummy;

    public MyClip() {

    }

    public MyClip(MyClip toCopy) {
        dummy = toCopy.dummy;
    }

    public Clip get() {
        return dummy;
    }

    public void set(Clip c) {
        this.dummy = c;
    }

    @Override
    public Object clone() {
        return new MyClip(this);
    }

}

public static void main(String... args) {
    MyClip original = new MyClip();
    MyClip clone1 = (MyClip)original.clone();
    MyClip clone2 = new MyClip(original);
}

Еще одна хорошая вещь в написании конструктора копирования для копирования вашего объекта состоит в том, что есть естественный способ сделать так, чтобы ваш суперкласс внес свой вклад в операцию копирования, вызывая его конструктор копирования с помощью 'super (toCopy);' сначала, а затем скопировать поля в свой собственный подкласс. Это неприменимо здесь, потому что вы реализуете интерфейс, но важно, если вы расширяете другой класс.

2 голосов
/ 26 марта 2019
class MyClip implements Cloneable {

    Clip dummy;

    public MyClip() {

    }

    public Clip get() {
        return dummy;
    }

    public void set(Clip c) {
        this.dummy = c;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        return super.clone();
    }    
}

если вы пишете такой код, вы в основном говорите: «Класс Object знает все о моем пользовательском классе, включая его создание». Конечно, это не так.

Вам нужно будет адаптировать метод клонирования к вашим потребностям:

class MyClip implements Cloneable {

    Clip dummy;

    public MyClip() {

    }

    public Clip get() {
        return dummy;
    }

    public void set(Clip c) {
        this.dummy = c;
    }

    @Override
    protected Object clone() throws CloneNotSupportedException {
        MyClip clone = new MyClip(); // create a new instance of your class
        clone.set(this.dummy);       // make sure it has the same value for 'dummy'
                                     // I would suggest improvement on your setter and getter name, though
        return clone;  // This returns an instance of MyClip, which has the exact same
                       // state as your current, but is a clone, and not the same instance.
    }

}

Чтобы вызвать это, вам нужно что-то вроде этого:

public void getClone(MyClip original) {
  MyClip Clone = (MyClip)original.clone();
}

EDIT: В соответствии с вашей проблемой, когда «фиктивный» оригинал также заражен, если вы хотите предотвратить это, просто включите в класс Clip также реализацию Cloneable и включите свой метод клонирования следующим образом:

@Override
        protected Object clone() throws CloneNotSupportedException {
            MyClip clone = new MyClip(); 
            clone.set(this.dummy == null ? null : this.dummy.clone());     
            return clone;                            
        }
...