1

I have an abstract super class and a few derived class.
I want to create a method

createNew()   

when invoked on a derived class it will create a new instance of the derived with a smart copy of all of its members.
All the members that are important for the creation are in the abstract class so the code should be the same.
can I write the implementation of createNew() in the super class?

something like that

SonA sonA2 = sonA1.createNew()   
SonB sonB2 = sonB1.createNew()  

the abs superclass should do the implementation because the code is identical .
thanks.

4 Answers 4

3

The implementation should be split between the abstract and the concrete classes. You can do it using the Template Method pattern:

public abstract class AbstractSon {
    protected abstract AbstractSon createNewImpl();
    public AbstractSon createNew() {
        AbstractSon res = createNewImpl();
        res.name = "default name";
        return res;
    }
}
public class Son1 extends AbstractSon {
    protected AbstractSon createNewImpl() {
        return new Son1();
    }
}
public class Son2 extends AbstractSon {
    protected AbstractSon createNewImpl() {
        return new Son2();
    }
}

You can split the responsibility differently to get the precise return type:

public abstract class AbstractSon {
    protected void prepare(AbstractSon toPrepare) {
        toPrepare.name = "default name";
    }
}
public class Son1 extends AbstractSon {
    public Son1 createNew() {
        Son1 res = new Son1();
        prepare(res);
        return res;
    }
}
public class Son2 extends AbstractSon {
    public Son2 createNew() {
        Son2 res = new Son2();
        prepare(res);
        return res;
    }
}
Sign up to request clarification or add additional context in comments.

2 Comments

isn't this actually c# code? Shouldn't you use "extends" rather than : ?
@david99world Oops, you're right - I've been doing too much C# lately. This is now fixed, thanks!
1

Make an abstract method that will serve as a callback used by your createNew method -- and implement that method in each subclass. createNew can be a concrete, even final method of the common superclass. The mentioned abstract method will return a new instance of the respective subclass.

An alternative approach is to find out through reflection on which class createNew was called and make a new instance based on that.

2 Comments

Note that in the OP's example SonA.createNew() and SonB.createNew() have different return types.
@aix Not necessarily, it could be <T> createNew(). It's going to work for that particular use case, but in a more complex expression it won't be of use.
1

You can write this code (using reflection: getClass().newInstance() to get an instance of the actual class instead of the class in which the method is defined) but it has some problems. For example what do you intend to return from this method?

You have to return the super type which means you have to cast for every invocation.

The usual solution is to define a copy() method that you define on every level. Then you can do this:

 class SonA {
     SonA createNew() {
         SonA result = new SonA();
         this.copy( result );
         return result;
     }

     void copy( SonA target ) {
         super.copy( target );

         // copy my fields to target ...
     }
 }

You may also want to read about copy constructors.

Comments

1

One possibility is to factor the copying out into a separate method, and call that from the derived classes' createNew():

abstract class Base {

  public abstract Base createNew();

  protected void populate(Base out) {
    // copy the data from `this' to `out'
  }
}

class Derived1 extends Base {
  public Derived1 createNew() {
    Derived1 ret = new new Derived1();
    populate(ret);
    return ret;
  }
}

class Derived1 extends Base {
  public Derived2 createNew() {
    Derived2 ret = new new Derived2();
    populate(ret);
    return ret;
  }
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.