5

Say that I have one constructor that takes an input and another that uses a default value. Both constructors then proceed to process this data in exactly the same way. (Example below.) What are my options to avoid code duplication in this case?

(I've read the post how to reduce the code of constructor overloading, where the top answer suggests using the keyword "this". In my case, I guess I would need to use "this" to call the first constructor from the second one after the input has been stored. This however results in a compilation error: "call to this must be first statement in constructor".)

Example code:

public class A {
  public A(String a) {
    //process a
  }
  public A() {
    String a = "defaultString";
    //process a
  }
}

EDIT: I'm taking a lot of fire for using an input dialog call in a class constructor (which I'm aware isn't exactly good practice). So I've changed the code example to direct the discussion away from this :).

4

6 に答える 6

10

One way is to have an init method:

public class A {
    public A(String a) {
        init(a);
    }
    public A() {
        String a = "defaultString";
        init(a);
    }
    private void init(String a) {
        //process a
    }
}
于 2012-05-07T21:50:33.683 に答える
5

Say that I have one constructor that takes an input and another that asks for it via an input dialog.

Don't do that. It will make for horribly entangled and hard to maintain code in the long run. At least try to seperate UI concerns (input dialogs etc) from your object model (which you can feed a string in the constructor).

In my honest opinion you really don't want an overloaded constructor here.

于 2012-05-07T21:54:25.273 に答える
3

You may want to try chaining your constructors:

public class A {
  public A(String a) {
    //process a
  }
  public A() {
    this("defaultString");
  }
}

If you want to use a dialog to get the string, I recommend you present the dialog before calling this constructor.

于 2012-05-08T15:36:50.050 に答える
1

I think this is the preferred method:

public class A {
  public A(String a) {
    //process a
  }
  public A() {
    this(JOptionPane.showInputDialog("a"));
  }
}
于 2012-05-07T21:54:11.033 に答える
0

I'm not sure it is ever a good idea to call something like a JOptionPane from a constructor. This is just an idea but you really should take the buildA from a static method and perform it where you actually are intending on asking the user for input and then just call a single constructor.

public class A {
  public A(String a) {
    this.a = a;
  }
  public static A buildA(String input){
    if(input == null){
      input = JOptionPane.showInputDialog("a"); 
    }
    return new A(input);
  }
}
于 2012-05-07T21:54:12.030 に答える
0

Another option for reducing code duplication between constructors is to use an initialization block. Initialization block code will run before the constructor.

See

Using this method, you could put the common code into the initializer block, then leave the different logic in the specific constructor.

public class A {
  {
     //initializer block - common code here
  }
  public A(String a) {
    //constructor - specific code here
  }
  public A() {
    //constructor - specific code here
  }
}

This may not be ideal in all situations, but it is another way to approach the problem that I didn't see mentioned yet.

于 2012-05-07T22:09:18.823 に答える