java copy constructor and inheritance

2019-02-23 04:23发布

问题:

After some searching I didn't found any good answer to my question regarding copy constructor and inheritance. I have two classes: User and Trainee. Trainee inherits from User and two String parameters are added to Trainee. Now I managed to make a copy constructor of User but I am not satisfied with my copy constructor of Trainee. The code of the User copy constructor is like this:

public User (User clone) {
    this(clone.getId(), 
         clone.getCivilite(),
         clone.getNom(), 
         clone.getPrenom(), 
         clone.getEmail(), 
         clone.getLogin(), 
         clone.getTel(), 
         clone.getPortable(), 
         clone.getInscription(), 
         clone.getPw()
    );
}

I tried to use super in my Trainee copy constructor:

public Trainee (Trainee clone) {
    super (clone);
    this (clone.getOsia(), clone.getDateNaiss());
}

But it didn't work and I was forced to code a full version of the copy constructor:

public Trainee (Trainee clone) {
    this(clone.getId(), 
         clone.getCivilite(),
         clone.getNom(),
         clone.getPrenom(), 
         clone.getEmail(), 
         clone.getLogin(), 
         clone.getTel(), 
         clone.getPortable(), 
         clone.getInscription(), 
         clone.getPw(), 
         clone.getOsia(), 
         clone.getDateNaiss()
    );
}

Because of the construction of my main I have to cast my new instance like this:

  User train = new Trainee();
  User train2 = new Trainee((Trainee) train);

So my question is: Is there a cleaner way to do this? Can't I use a super?

Thank you in advance for your answers and assistance.

回答1:

It would be better to make the "full" copy constructor for Trainee also take a User:

public Trainee(Trainee clone)
{
    this(clone, clone.getOsai(), clone.getDateNaiss());
}

public Trainee(User clone, String osai, String dateNaiss)
{
    super(clone);
    this.osai = osai;
    this.dateNaiss;
}

As far as possible, it's worth keeping to the pattern of having one "master" constructor in each class, which all other constructors chain to, directly or indirectly.

Now, it isn't clear whether it makes sense to create a Trainee without specifying existing user information... or possibly specifying it in some other way. It may be that in this case you really do need to have two separate sets of constructors - one set for copy constructors, and one set for "just give me all the values individually" constructors. It really depends on your context - we can't tell just from this.

In that case, you would be breaking the "one master constructor" rule slightly, but you can think of there being two master constructors, one for each set of constructors for different purposes. Fundamentally, you're running into "inheritance gets messy" - which is all too common :(



回答2:

I would do:

 public Trainee (User clone) // By specifying `User` you allow the use in your code
 {
    super (clone);
    if (clone instanceof Trainee) {
      this.osia = clone.getOsia();
      this.dateNaiss = clone.getDateNaiss());
    }
 }