简体   繁体   中英

Java condition at constructor in order to invoke a parent constructor

I have a following Java class:

public class CharacteristicResponse extends VotableResponse {

    public CharacteristicResponse() {
    }

    public CharacteristicResponse(Characteristic characteristic) {
        super(characteristic);

        this.characteristicId = characteristic.getId();
        this.name = characteristic.getName();
        this.nameSlug = characteristic.getNameSlug();
        this.description = characteristic.getDescription();
        this.valueType = characteristic.getValueType();
        this.visualMode = characteristic.getVisualMode();

        ...

    }

}

I want to add additional argument to constructor in order to be able to control super constructor invocation.. for example something like this:

public CharacteristicResponse(Characteristic characteristic, Boolean detailed) {
    if(detailed) {
        super(characteristic);
    }
...

}

The example above is not possible from Java point of view so I'm looking for a solution how it can be done at some other way.

In a comment you've said:

Currently I have a pretty deep chain of a nested super calls.. so I was wondering there is an elegant way how it can be done with no needs to rewrite a lot of code..

In terms of not shaking that up too much, I see basically three options:

  1. You could pass null in the case detailed is false and have VotableResponse(Characteristic) handle getting null :

     super(detailed ? characteristic : null); 
  2. You could always call super() and then then set characteristic via a setter immediately afterward if detailed is true.

     super(); if (detailed) { super.setCharacteristic(characteristic); } 
  3. You could pass the flag up the chain and let each class along the way handle it appropriately.

The example above is not possible from Java point of view so I'm looking for a solution how it can be done at some other way.

Indeed, in Java the super constructor invocation is mandatory. If you have only a constructor with some args you are forced to invoke it from the child class to compile fine
If the super constructor of the class doesn't suit for all cases, it means probably that what you perform in the super constructor should not be done here.

You could move the processing that is actually in the parent constructor directly to the child class constructor that needs it or in a common abstract class if multiple child classes need it.

You can just have a setter method. Or try moving the logic to the factory. Factory Design Pattern But if you dont have access to the data structure of the backend, just you need to pass some parametters to the back end just use the .setCharacteristics(Characteristic characteristic, Boolean detailed)

If you really want to pass in a flag, create a factory that handles construction of new objects in this hierarchy:

class ResponseFactory {
  public Response buildCharacteristicResponse(Characteristic characteristic, Boolean detailed) {
    if (detailed) {
      return new DetailedCharacteristicResponse(characteristic);
    } else {
      return new SimpleCharacteristicResponse(characteristic);
    }
  }
}

class Characteristic {}

class Response {
  public Response(final Characteristic characteristic) {
  }
}

class DetailedCharacteristicResponse extends Response {
  public DetailedCharacteristicResponse(final Characteristic characteristic) {
    super(characteristic);
  }
}

class SimpleCharacteristicResponse extends Response {
  public SimpleCharacteristicResponse(final Characteristic characteristic) {
    super(characteristic);
  }
}

I am assuming VotableResponse has an empty constructor? Your first example is implicitly calling super() in the empty constructor for CharacteristicResponse . You will have to invoke a super constructor one way or the other and it has to be the very first line of your constructor.

You may also try using static instantiators

public class CharacteristicResponse extends VotableResponse {

public CharacteristicResponse() {
}

public CharacteristicResponse(Characteristic characteristic) {
    super(characteristic);

}

public static CharacteristicResponse instanceFrom(Characteristic c, boolean detailed)
    if (detailed) {
      return new CharacteristicResponse(c);
    } else {
      return new CharacteristicResponse();  
    }
}

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM