Kotlin: 次构造函数参数上的 'val' 不被允许。

13

我有以下的类:

class Person(val name: String) {
    private var surname: String = "Unknown"

    constructor(name: String, surname: String) : this(name) {
        this.surname = surname
    }
}

但是当我想在第二个构造函数中使name参数不可变时:

constructor(val name: String, surname: String) : this(name) {
    this.surname = surname
}

我遇到了以下编译时错误:

Kotlin:在次要构造函数参数上使用'val'是不允许的

有人能解释一下为什么 Kotlin 编译器不允许这样做吗?


name是不可变的引用,因为它在主构造函数中被声明为val - Eugen Pechanec
在 Kotlin 函数和构造函数中,所有参数都是不可变的,例如 fun foo(name : String) 在 Java 中转换为 public void foo(@NotNull final String name) - msrd0
@msrd0 主构造函数可以使用val/var。 - BertKing
@BertKing 是啊,真是个惊喜... - msrd0
4个回答

32

Kotlin中的参数始终是不可变的。将构造函数参数标记为val会将其转换为类的属性,这只能在主构造函数中完成,因为类的属性集合不能根据用于创建类实例的构造函数而变化。


4

除了yole的好答案外,文档也非常清晰:

请注意,主构造函数的参数可以在初始化块中使用。它们也可以在类体中声明的属性初始化器中使用。 [...] 实际上,为了声明属性并从主构造函数初始化它们,Kotlin有一种简洁的语法:

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

与常规属性类似,主构造函数中声明的属性可以是可变的(var)或只读的(val)。这一点并不适用于辅助构造函数。

0

你可以在继承的类中将变量定义为 val 或 var

   open class Human(val name: String) constructor(name: String) {
            open fun showInfo()
        {
            println("Show Info")
        }
        }

class Person:Human {

constructor(name: String) : super(name)
    private var surname: String = "Unknown"
  override fun showInfo() {
        println("$name And surname is $surname")
    }
    
}

虽然你的解决方案可以工作,但它会不必要地增加复杂性。更好的方法是简化原始类并使用一个主构造函数,其中包含一个可选参数来表示姓氏。 - flamewave000

0

目前被接受的答案在解释为什么您的初始尝试不起作用方面是正确的。因此,考虑到您的特定情况,我建议反转解决方案并将您的次要构造函数作为主要构造函数,并使第二个参数具有默认值。

class Person(val name: String, private var surname: String = "Unknown")

此外,如果该类的目的仅在于保存数据,我会将其设置为一个data class以改善其处理。

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