Kotlin 有没有一种方法可以;禁用";主构造函数还是强制用户始终使用辅助构造函数?

Kotlin 有没有一种方法可以;禁用";主构造函数还是强制用户始终使用辅助构造函数?,kotlin,Kotlin,例如: data class Car ( val type: TypeEnum, val brand: BrandEnum, val modelNumber: Int) { constructor(val type: TypeEnum, val brand: BrandEnum, val input: String) : this ( type, brand,

例如:

data class Car (
    val type: TypeEnum,
    val brand: BrandEnum,
    val modelNumber: Int) 
{
    constructor(val type: TypeEnum, 
                val brand: BrandEnum,
                val input: String) : this (
        type,
        brand,
        Valdidator.validateModelNumber(input)
    )
}
在上面的代码中,validateModelNumber()方法验证原始输入,如果型号的格式无效,则引发异常。我想强制用户在每次创建汽车对象时都使用此构造函数


本质上:我想确保不存在无效的Car对象,同时使代码尽可能不可变。

您可以使用
init
块。像这样的

data class Car (
    val type: TypeEnum,
    val brand: BrandEnum,
    val modelNumber: Int)
{
    init {
        Valdidator.validateModelNumber(input)
    }
}

如果只需要主构造函数中指定的参数/属性,那么使用
init
块进行验证(根据另一个答案)可以很好地工作

如果不希望主构造函数被其他代码使用,可以通过更改以下内容使其成为私有的:

data class Car(
致:

然后,您可以留下一个公共的二级构造函数供其他类使用,如问题中所述。但是,这仍然有点限制,因为在调用主构造函数之前,您不能进行任何认真的处理

因此,通常的模式是在伴生对象中有一个私有构造函数和工厂方法;您甚至可以返回缓存实例、子类实例等

通过使用合适的参数将它们实现为
operator fun invoke()
,可以使它们看起来像构造函数

data class Car private constructor(
    val type: TypeEnum,
    val brand: BrandEnum,
    val modelNumber: Int) 
{
    companion object {
        operator fun invoke(type: TypeEnum, brand: BrandEnum, input: String)
            = Car(type, brand, Validator.validateModelNumber(input))
    }
}
然后,您可以创建实例,例如:

Car(TypeEnum.SPORTS, BrandEnum.ASTON_MARTIN, "DB5")
看起来就像一个普通的构造函数

Car(TypeEnum.SPORTS, BrandEnum.ASTON_MARTIN, "DB5")