不变的(数据)类上的多个构造函数[英] Multiple constructors on an immutable (data) class

本文是小编为大家收集整理的关于不变的(数据)类上的多个构造函数的处理方法,想解了不变的(数据)类上的多个构造函数的问题怎么解决?不变的(数据)类上的多个构造函数问题的解决办法?那么可以参考本文帮助大家快速定位并解决问题。

问题描述

我正在尝试使用多个构造函数实现不变的数据类.我觉得这样的事情应该是可能的:

data class Color(val r: Int, val g: Int, val b: Int) {
   constructor(hex: String) {
        assert(Regex("#[a-fA-F0-6]{6}").matches(hex), { "$hex is not a hex color" } )
        val r = hex.substring(1..2).toInt(16)
        val g = hex.substring(3..4).toInt(16)
        val b = hex.substring(5..6).toInt(16)
        this(r,g,b)
    }
}

当然不是:Kotlin期望在顶部声明对主要构造函数的呼叫:

constructor(hex: String): this(r,g,b) {
    assert(Regex("#[a-fA-F0-6]{6}").matches(hex), { "$hex is not a hex color" } )
    val r = hex.substring(1..2).toInt(16)
    val g = hex.substring(3..4).toInt(16)
    val b = hex.substring(5..6).toInt(16)
}

这也不好,因为呼叫是在构造器主体之前执行,无法访问本地变量.

我可以做当然:

constructor(hex: String): this(hex.substring(1..2).toInt(16),
                               hex.substring(3..4).toInt(16), 
                               hex.substring(5..6).toInt(16)) {
    assert(Regex("#[a-fA-F0-6]{6}").matches(hex), { "$hex is not a hex color" } )
}

但这将检查该断言为时已晚,并且缩放不太舒适.

我看到接近所需行为的唯一方法是使用助手函数(在Color上无法定义非静态功能):

constructor(hex: String): this(hexExtract(hex, 1..2), 
                               hexExtract(hex, 3..4), 
                               hexExtract(hex, 5..6))

这不会使我成为一种非常优雅的模式,所以我猜我在这里错过了一些东西.

是否有一种优雅的,惯用的方法可以在Kotlin的不变数据类别上拥有(复杂的)次级构造函数?

推荐答案

如解释的那样在这里 companion对象上的操作函数invoke(就像Scala's apply一样)可以实现真正的构造函数,而是一个看起来像构造函数的工厂::

companion object {
    operator fun invoke(hex: String) : Color {
        assert(Regex("#[a-fA-F0-6]{6}").matches(hex),
               {"$hex is not a hex color"})
        val r = hex.substring(1..2).toInt(16)
        val g = hex.substring(3..4).toInt(16)
        val b = hex.substring(5..6).toInt(16)
        return Color(r, g, b)
    }
}

现在,Color("#FF00FF")将对预期的东西.

其他推荐答案

按照@nhaarman的建议,一种方法是使用工厂方法.我经常使用以下内容:

data class Color(val r: Int, val g: Int, val b: Int) {
   companion object {
        fun fromHex(hex: String): Color {
            assert(Regex("#[a-fA-F0-6]{6}").matches(hex), { "$hex is not a hex color" } )
            val r = hex.substring(1..2).toInt(16)
            val g = hex.substring(3..4).toInt(16)
            val b = hex.substring(5..6).toInt(16)
            return Color(r,g,b)
        }
    }
}

,然后您可以用Color.fromHex("#abc123")

调用它

本文地址:https://www.itbaoku.cn/post/1794026.html