【问题标题】:Kotlin primary constructor calling secondary constructorKotlin 主构造函数调用辅助构造函数
【发布时间】:2019-01-10 10:57:16
【问题描述】:

为什么不编译?

class test
{
  constructor() {
      var a = Date().day
      this(a)
  }

  constructor(a:Int) {
  }
}

错误是: 'test' 类型的表达式 'this' 不能作为函数调用。找不到函数'invoke()'。

建议的解决方法是添加以下内容:

private operator fun invoke(i: Int) {}

为什么?

【问题讨论】:

    标签: kotlin class-constructors multiple-constructors


    【解决方案1】:

    首先,这两个构造函数都是辅助构造函数。主构造函数是位于类主体之外的构造函数。

    其次,如documentation中所述,调用另一个构造函数的正确语法如下:

    class Test {
        constructor() : this(1) { }
    
        constructor(a: Int) { }
    }
    

    【讨论】:

    • 如果在调用二级构造函数之前需要做一些计算如:class test { constructor() { var a = Date().day this(a) } constructor(a:Int) { } }
    • 你不能这样做。这是 JVM 限制。如果这是可能的,那么在执行var a = Date() 期间,该对象将处于未初始化状态,这是不允许的。
    • 等待...根据您的计算,您可以,例如您可以写:constructor() : this(Date().day) 或者我只是没有正确理解您的问题 ;-) 如果这是一个更复杂的计算但您从某个地方的新实例开始,您可以使用类似 constructor() : this(ComplexObject().let { /* complex function leading to Int */ })
    【解决方案2】:
    class test constructor(){ // primary constructor (The primary constructor is part of the class header: it goes after the class name (and optional type parameters))
    
        constructor(a: Int) : this() { // secondary constructor
    
        }
    }
    

    如果你的班级定义了primary constructorsecondary constructor 需要委托给primary constructor。见here

    我认为primary constructor 不能secondary constructor 调用。

    你可以这样想:secondary调用primary,primary调用secondary =>无限循环=>不可能

    在你的情况下,有 2 个secondary constructor,所以你可以这样做

    class test {
    
        constructor() : this(Date().day) // I see it quite like Java here https://stackoverflow.com/questions/1168345/why-do-this-and-super-have-to-be-the-first-statement-in-a-constructor
    
        constructor(a: Int) {
        }
    }
    

    【讨论】:

      【解决方案3】:

      这里有几件事是错误的:

      • 类的名称应始终使用驼峰式 (test -> Test)
      • 您不能像尝试那样调用另一个构造函数(在其他构造函数主体内调用 this(1)

      我认为您真正想要的是 a 是一个属性,或者使用默认值对其进行初始化。你可以这样做

      class Test(val a: Int) {
          constructor() : this(1) // notice how you can omit an empty body
      }
      

      甚至更好,像这样:

      class Test(val a: Int = 1) // again an empty body can be omitted.
      

      编辑:

      如果您需要进行一些计算,如 Yole 回答下方的评论中所问:

      class Test(val day: Int) {
          // you can use any expression for initialization
          constructor(millis: Long) : this(Date(millis).day) 
      }
      

      或者如果事情变得更复杂:

      class Test(var day: Int) {
          // pass something (i.e. 1) to the primary constructor and set it properly in the body
          constructor(millis: Long) : this(1) { 
              // some code
              day = // initialize day
          }
      }
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2019-04-10
        • 2015-01-28
        • 1970-01-01
        相关资源
        最近更新 更多