计算构造函数中未显示的字段

时间:2019-05-06 12:58:14

标签: kotlin

假设我有一个包含3个字段的类:A,B和C。我可以通过两种方式创建该类的实例:将所有字段传递给构造函数,或者仅传递A,其他属性将基于在A上。

class App extends React.Component {
  state = {
    value: moment(),
  };

  handleValueChange = (value, id) => {
    console.log(value && value.format('HH:mm:ss'));
    console.log(id);
    this.setState({ value });
  };

  clear = () => {
    this.setState({
      value: undefined,
    });
  };

  render() {
    const { value } = this.state;
    return (
      <div>
        <TimePicker
        id={item.day}
        defaultValue={value}
        onChange={(value, id=item.day) => this.handleValueChange(value, id)}
    />
        <button onClick={this.clear} type="button">
          clear
        </button>
      </div>
    );
  }
}

此方法使用两个主要构造函数,而没有主要构造函数。但是从我的角度来看,它看起来很沉重。是否可以用更优雅的方式重写此逻辑?

3 个答案:

答案 0 :(得分:3)

也许您可以采取以下措施。您可能希望将Pair替换为实际类型,然后...

class MyClass(
        val A: String,
        val BC : Pair<String, String>
) {
    constructor(A: String, B: String, C: String) : this(A, B to C) // is this then even needed?
    constructor(A : String) : this(A, Calculator.calculate(A))
}

或者,如果更合理的话,则具有三个单独的属性,反之亦然,k0enf0rNL 也显示了这一点:

class MyClass(
     val A: String,
     val B: String,
     val C: String
) {
  constructor(A: String) : this(A, Calculator.calculate(A))
  constructor(A: String, BC : Pair<String, String>) : this(A, BC.first, BC.second)
}

最后,如果您不想公开某些构造函数,请随意将其标记为private,例如以下内容将与您显示的示例相同:

class MyClass(
     val A: String,
     val B: String,
     val C: String
) {
  constructor(A: String) : this(A, Calculator.calculate(A))
  private constructor(A: String, BC : Pair<String, String>) : this(A, BC.first, BC.second)
}

也许您宁愿需要一些东西来传递函数(因为您还使用了Calculator.calculate(A))。然后,您可能需要添加以下内容作为构造函数:

constructor(A : String, func: (String) -> Pair<String, String> = Calculator::calculate) : this(A, func(A))

如果这从一开始就是您想要的,那么即使是如下所示的类也可能适合您:

class MyClass(val A: String,
              func: (String) -> Pair<String, String> = Calculator::calculate) {
    val B: String
    val C: String

    init {
        func(A).also { (newB, newC) ->
            B = newB
            C = newC
        }
    }
}

如果您随后只想传递ABC而没有实际的计算(或传递的函数),则仍然可以按照以下步骤进行(基本上丢弃传递的{ {1}}):

A

答案 1 :(得分:2)

我个人最喜欢的是滥用伴侣对象调用运算符:

class MyClass(val A: String, val B: String, val C: String) {

    companion object {
        operator fun invoke(A: String): MyClass {
            val (B, C) = Calculator.calculate(A)
            return MyClass(A, B, C)
        }
    }
}

答案 2 :(得分:0)

您可以将其编写为数据类,并且至少可以像这样摆脱默认构造函数

data class MyClass(
    val A: String,
    val B: String,
    val C: String
) {
    constructor(A: String, calculated: Pair<String, String> = calculate()) : this(
        A,
        calculated.first,
        calculated.second
    )
}

fun calculate() : Pair<String, String> = "this" to "that"