Kotlin中的构造函数

42

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

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

我想再创建一个构造函数,这个构造函数将在一个构造函数中接受一个参数。在Kotlin中如何实现?

6个回答

58

好的,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) 调用主构造函数吗?如果是,我们能记录日志进行检查吗? - N Sharma
this() 用于调用构造函数,其参数签名定义了要调用哪个构造函数。 - Sachin Chandil
是的,没错。我们可以通过记录来检查它是否调用了主构造函数吗? - N Sharma
1
根据文档所述,主构造函数没有主体,但您可以将该代码放在 init 块中,就可以解决问题。 - Sachin Chandil
如果我们将构造函数视为一种特殊的方法或函数,那么关于这个参数(名称),它不是一个返回类型吗? - Farruh Habibullaev
返回类型是什么?构造函数不返回任何值。@FarruhHabibullaev - Sachin Chandil

4

第一种方式是使用空值

// (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 不允许使用 nullthis(name,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");
    }
}

1
在类内部使用 constructor 关键字创建辅助构造函数。例如:
class Person(name: String, surname: String) {
    init {
        Log.d("App", "Hello");
    }
    constructor(id: Int) {

    }
}

了解更多信息,请查看次级构造函数

编辑:
规则:如果类具有主构造函数,则每个次级构造函数都需要直接或间接地通过另一个次级构造函数将委托传递给主构造函数。使用this关键字可以将委托传递到同一类的另一个构造函数中。

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

当您调用二级构造函数时,它会调用主构造函数来初始化名称,然后您可以在二级构造函数中进行其他操作。在上面的示例中,通过调用主构造函数来初始化名称。

1
我有这段代码 `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`。 - N Sharma
这是因为你必须使用this关键字调用主构造函数。我很快会写一个答案来演示。 - Alf Moh

1

次级构造函数

类还可以声明次级构造函数,它们以 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的“Secondary Constructors”部分。


1

这是创建另一个构造函数的方法。

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

}
}

始终记住,次要构造函数将必须使用this关键字引用主构造函数及其参数。

0
使用变量“internal”,然后您可以在单个类中添加多个构造函数,如下所示。
class AuthModel {
var code: String? = null

internal constructor(code: String?) {
    this.code = code
}

internal constructor() {}
}

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接