Copy Constructor in Child but not Parent
I have the following two classes:
public class User {
public Integer userId;
// ...another 50-60 fields
}
public class SuperUser extends User {
}
I would like to have a constructor in SuperUser which takes an object of type User and creates an object of type SuperUser. For example:
public SuperUser(User th开发者_JS百科eUser) {
// not legal -> but I am looking for a one-liner to initialize this with values from theUser
this = theUser;
}
If the User object lacks the constructor User(User existingUser), is there any automatic way to initialize the SuperUser object with all of the fields from the existing user object? I'm trying to avoid 50 lines of:
public SuperUser(User theUser) {
this.firstName = theUser.getFirstName();
this.lastName = theUser.getLastName();
// and so on....
}
If this cannot be done, is there a refactoring like "Create Copy Constructor?"
Thanks!
Take a look at commons-beanutils's BeanUtils.copyProperties(..)
:
SuperUser superUser = new SuperUser();
BeanUtils.copyProperties(superUser, originalUser);
Alternatively you can place this in the copy-constructor:
public SuperUser(User originalUser) {
BeanUtils.copyProperties(this, originalUser);
}
While you could use something like BeanUtils to do what you are trying to do, if you need to promote a User to SuperUser or demote a SuperUser to a User, are you using the right abstraction.
Could you refactor your code so that the User has permissions or privileges? In general when I feel I need to change an object to a different object in the hierarchy, I rearrange the hierarchy.
For example:
public class User {
public Integer userId;
// ...another 50-60 fields
public Role role;
}
public interface Role {
}
public SuperUserRole implements Role {
}
If you don't want to make this change, then Bozho's answer would work.
Reflection & BeanUtils are handy, but slow. May be worth the trade-off in your case, but I'd avoid them. Also, Object.clone() will not give you what you want.. because User's clone() method (if implemented.. and it's probably not).. will give you a User.. not a SuperUser.
clone() is rarely used. Copy constructor or a factory method are both reasonable patterns.
Edit: Forgot to answer the question. Yep, manually implement the copy constructor. Java == Lots of Typing.
The java.beans
package can handle this stuff:
User u = ...;
SuperUser su = ...;
BeanInfo bi = Introspector.getBeanInfo(User.class);
for (PropertyDescriptor pd : bi.getPropertyDescriptors()) {
Method getter = bi.getReadMethod(), setter = bi.getWriteMethod();
if (getter == null || setter == null) continue;
setter.invoke(su, getter.invoke(u));
}
// ...another 50-60 fields.
Instead of String firstName
etc, User should have fields like Name name
, which has first, last, title etc.
You could do the same for your addresses, contact details etc. This would make a copy constructor rather easier.
BTW, since SuperUser extends User, your constructor would be
public SuperUser(User user){
super(user); //the User constructor would do the copy
//initialize other fields...
}
If you want use BeanUtils on Android but no luck, try android-java-air-bridge instead. https://code.google.com/p/android-java-air-bridge/
Just download the android-java-air-bridge.jar.zip, extract the .jar and import into your project, no need change any code.
Example:
import javadz.beanutils.BeanUtils;
BeanUtils.copyProperties(superUser, originalUser);
精彩评论