【问题标题】:Constructors in KotlinKotlin 中的构造函数
【发布时间】:2017-05-31 05:20:39
【问题描述】:

我正在从官方文档中学习Kotlin,我创建了一个class,如下所示,我创建了一个constructor,其中有两个parametersconstructor 的正文在 init 块中。

class Person(name: String, surname: String) {
    init {
        Log.d("App", "Hello");
    }
}

好吧,我想再创建一个constructor,它将在constructor 中使用一个parameterKotlin里面有什么办法

【问题讨论】:

    标签: android constructor kotlin


    【解决方案1】:

    init 不是构造函数的主体。它在主构造函数之后调用,带有主构造函数的上下文。

    在官方文档中给出:

    主构造函数不能包含任何代码。初始化代码可以放在初始化块中,以init关键字为前缀:

    class Customer(name: String) {
        init {
            logger.info("Customer initialized with value ${name}")
        }
    }
    

    请注意,主构造函数的参数可以在初始化块中使用。它们也可以用在类主体中声明的属性初始化器中:

    class Customer(name: String) {
        val customerKey = name.toUpperCase()
    }
    

    事实上,对于声明属性并从主构造函数初始化它们,Kotlin 有一个简洁的语法:

    class Person(val firstName: String, val lastName: String, var age: Int) {
        // ...
    }
    

    根据您的问题,您可以添加一个构造函数来接受一个参数,如下所示:

    class Person(name: String, surname: String) {
    
        constructor(name: String) : this(name, "") {
            // constructor body
        }
    
        init {
            Log.d("App", "Hello");
        }
    }
    

    但它看起来不正确,因为我们没有必要传递第二个参数空字符串。所以我们可以像下面这样订购构造函数:

    class Person(name: String) {
    
        constructor(name: String, surname: String) : this(name) {
            // constructor body
        }
    
        init {
            Log.d("App", "Hello");
        }
    }
    

    希望对你有帮助。

    【讨论】:

    • this(name) 是否调用主构造函数?如果可以,我们可以登录检查吗?
    • this() 用于调用构造函数,其参数签名定义了调用哪个构造函数。
    • 没错。我们可以通过记录来检查它是否调用了主构造函数?
    • 如文档中给出的主构造函数没有主体,但您可以将该代码放在init 块中,它应该可以解决问题。
    • this(name)上的一个参数,如果我们把构造函数看成一个特殊的方法或者func,那么this(name)不就是一个返回类型吗?
    【解决方案2】:

    空值的第一种方式

    // (name: String, surname: String)  default constructor signature
    class Person(name: String, surname: String) {
    
        // init block , represents the body of default constructor 
        init {
            Log.d("primary", "Hello");
        }
    
        // secondary constructor 
        // this(name,"") call to default constructor
        constructor(name : String):this(name,""){
            Log.d("secondary", "Hello");
        }
    }
    

    为什么this(name,"")

    如果类有一个主构造函数,则每个辅助构造函数 需要直接或直接委托给主构造函数 间接通过另一个辅助构造函数。委托给 同一类的另一个构造函数是使用 this 关键字完成的:

    kotlin 不允许像this(name,null) 一样使用null,所以使用? 来表示null 类型的值,surname: String?

    class Person(name: String, surname: String?) {
    
        init {
            Log.d("primary", "Hello");
        }
    
        constructor(name : String):this(name,null){
            Log.d("secondary", "Hello");
        }
    }
    

    【讨论】:

      【解决方案3】:

      辅助构造函数

      该类还可以声明二级构造函数,以constructor为前缀:

      class Person {
          constructor(parent: Person) {
              parent.children.add(this)
          } } 
      

      如果类具有主构造函数,则每个辅助构造函数都需要直接或通过另一个辅助构造函数间接委托给主构造函数。使用 this 关键字可以委托给同一类的另一个构造函数:

      class Person(val name: String) {
          constructor(name: String, parent: Person) : this(name) {
              parent.children.add(this)
          } }
      

      https://kotlinlang.org/docs/reference/classes.html二级构造函数部分

      【讨论】:

        【解决方案4】:

        在类内部使用constructor 关键字来创建二级构造函数。喜欢:

        class Person(name: String, surname: String) {
            init {
                Log.d("App", "Hello");
            }
            constructor(id: Int) {
        
            }
        }
        

        更多信息请查看Secondary Constructors

        编辑:
        规则: 如果类有主构造函数,则每个辅助构造函数都需要直接或间接通过另一个辅助构造函数委托给主构造函数。使用 this 关键字可以委托给同一类的另一个构造函数。

        class Person(val name: String) {
            constructor(name: String, parent: Person) : this(name) {
                parent.children.add(this)
            }
        }
        

        因此,当您调用辅助构造函数时,它会调用主构造函数来初始化名称,然后您在辅助构造函数中执行您的操作。在上面的示例中,名称是通过调用主构造函数来初始化的。

        【讨论】:

        • 我有这个代码class Person(name: String, surname: String) { init { Log.d("Hello", "Hello $name $surname"); } constructor(name: String) { } } 添加辅助构造函数后,Android Studio 提示我Error:(10, 5) Primary constructor call expected
        • 这是因为,您必须使用 this 关键字调用主构造函数。很快写一个答案来演示。
        【解决方案5】:

        这就是你创建另一个构造函数的方式。

        class Person(name: String, surname: String) {
            init {
                Log.d("App", "Hello");
            }
         constructor(id: Int) : this("example name", "example surname") {
        
        }
        }
        

        请记住,辅助构造函数必须使用 this 关键字引用主构造函数及其参数。

        【讨论】:

          【解决方案6】:

          使用变量“内部”,然后您可以在单个类中添加多个构造函数,如下所示。

          class AuthModel {
          var code: String? = null
          
          internal constructor(code: String?) {
              this.code = code
          }
          
          internal constructor() {}
          }
          

          【讨论】:

            猜你喜欢
            • 2018-04-01
            • 1970-01-01
            • 2019-06-19
            • 2019-01-10
            • 2018-04-23
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            相关资源
            最近更新 更多