简体   繁体   English

如何避免重载构造函数中的代码重复?

[英]How to avoid code duplication in overloaded constructors?

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".) (我已经阅读了如何减少构造函数重载的代码,其中最佳答案建议使用关键字“this”。在我的情况下,我想我需要使用“this”从第二个构造函数调用第一个构造函数存储输入之后的一个。然而,这会导致编译错误:“调用 this 必须是构造函数中的第一个语句”。)

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 :).因此,我更改了代码示例以将讨论引向远离此 :)。

One way is to have an init method:一种方法是使用 init 方法:

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

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).至少尝试将 UI 问题(输入对话框等)与您的object模型(您可以在构造函数中提供一个string )分开。

In my honest opinion you really don't want an overloaded constructor here.老实说,你真的希望这里有一个重载的构造函数。

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.如果您想使用对话框来获取字符串,我建议您调用此构造函数之前显示对话框。

I think this is the preferred method:我认为这是首选方法:

public class A {
  public A(String a) {
    //process a
  }
  public A() {
    this(JOptionPane.showInputDialog("a"));
  }
}

I'm not sure it is ever a good idea to call something like a JOptionPane from a constructor.我不确定从构造函数调用 JOptionPane 之类的东西是否是一个好主意。 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.这只是一个想法,但您确实应该从静态方法中获取 buildA 并在您实际打算要求用户输入的地方执行它,然后只调用一个构造函数。

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);
  }
}

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.这在所有情况下可能并不理想,但这是解决我尚未看到的问题的另一种方法。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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