0

I have an abstract class with several subclasses. In the abstract classe I have implemented a copy constructor. Now, I want to clone one of the subclasses using the copy constructor, how can I do this? Obviously I do not know in advance what subclass I have to clone.

Here is an example of what I want to do :

abstract class AbstractClass {
    public AbstractClass(AbstractClass ac) {
        this();
        setX(ac.getX());
        setY(ac.getY());
    }

    // Some setter and getter for X and Y variables
}

class SubclassA extends AbstractClass {
    public SubclassA(SubclassA a) {
        super(a);
    }
}

class SubclassB extends AbstractClass {
    public SubclassB(SubclassB b) {
        super(b);
    }
}

public class Main {
    public static void main(String[] args) {
        AbstractClass a = new SubclassA();
        AbstractClass b = new SubclassB();

        // Get a copy of "a" or "b" using the copy constructor of abstract class        
        AbstractClass newA = AbstractClass(a);
        AbstractClass newB = AbstractClass(b);
    }
}
Jeankowkow
  • 814
  • 13
  • 33
  • 1
    Why don't you use `clone()` instead (remember to implement `Cloneable`)? It would then be `AbstractClass newA = a.clone()` and with covariant return types the method `SubclassA` could have a return type of `SubclassA` instead of `AbstractClass`. – Thomas Jun 16 '16 at 14:04
  • You can't use the Copyconstructor of your superclass, becaus it doesn't know implementation detailas of your subclasses. Use the copyconstructor of the subclasses, or use `clone()` – F. Lumnitz Jun 16 '16 at 14:12
  • [According to other comments, clone is not recommended.](http://stackoverflow.com/questions/4081858/about-java-cloneable) So I wanted to deal with copy constructor... But if there isn't other way to do that otherwise by the clone method, I will do that with the clone method. – Jeankowkow Jun 16 '16 at 15:35

2 Answers2

1

There are only two ways I can see to create a copy of a given object without knowing at compile time which class to instantiate (as requested in the question):

  1. Use Reflection to call the copy constructor of the desired class, assuming you know at runtime what the class is, and that said class has a suitable copy constructor.
  2. Call some copy method of the base class which is overridden by subclasses.

The first solution is not good as it requires the use of Reflection. The second can be implemented with the clone()/Cloneable standard mechanism (despite its issues), or with some custom-defined "copy()" method. Your choice.

Rogério
  • 16,171
  • 2
  • 50
  • 63
0
abstract class AbstractClass {
    public AbstractClass(AbstractClass ac) {
        this();
        setX(ac.getX());
        setY(ac.getY());
    }

    public abstract AbstractClass clone();

    // Some setter and getter for X and Y variables
}

class SubclassA extends AbstractClass {
    public SubclassA(SubclassA a) {
        super(a);
    }

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

class SubclassB extends AbstractClass {
    public SubclassB(SubclassB b) {
        super(b);
    }

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

public class Main {
    public static void main(String[] args) {
        AbstractClass a = new SubclassA();
        AbstractClass b = new SubclassB();

        // Get a copy of "a" or "b" using the copy constructor of abstract class        
        AbstractClass newA = a.clone(); // is instance of SubclassA
        AbstractClass newB = b.clone(); // is instance of SubclassB
    }
}

The trick here is to use your own clone method (which has nothing to do with Cloneable what so ever). This method in turns calls the proper copy constructor.

This means you get all the advantages of a copy constructor, and you can be sure that no matter hwta subclass of AbstractClass you get, you always get a copy of the proper subclass without needing to call the constructor yourself.

Polygnome
  • 7,639
  • 2
  • 37
  • 57