寻求有关在 Kotlin 中设计干净数据类(模型)的建议

问题描述 投票:0回答:1

我目前正在为 AlarmTime 实例设计一个简洁的数据类(模型),它将在 Alarm 类中扮演变量的角色。我提出了两种解决方案,我希望得到一些建议来确定哪一种更适合 Kotlin 约定,并且通常更适合这种情况。如果这两个想法有很大偏差,我将非常感谢您可以分享的任何示例或指导。

非常感谢!

解决方案1

data class AlarmTime private constructor(
    val hour: Int,
    val minute: Int,
) {
    fun toCombinedMinutes(): Int = hour * 60 + minute

    companion object {
        private const val MAX_COMBINED_MINUTES = 1439 // 23 * 60 + 59

        operator fun invoke(hour: Int, minute: Int) =
            when {
                hour >= 24 || hour < 0 -> throw IllegalArgumentException(
                    "Invalid hour value. Hour must be within the range of 0 to 23.")
                minute >= 60 || minute < 0 -> throw IllegalArgumentException(
                    "Invalid minute value. Minute must be within the range of 0 to 59.")
                else -> AlarmTime(hour, minute)
            }

        operator fun invoke(combinedMinutes: Int) =
            when {
                combinedMinutes > MAX_COMBINED_MINUTES || combinedMinutes < 0 ->
                    throw IllegalArgumentException(
                        "Invalid combined minutes value. " +
                                "Combined minutes must be within the range of 0 to 1439"
                    )
                else -> AlarmTime(
                    hour = combinedMinutes / 60,
                    minute =  combinedMinutes % 60
                )
            }
    }
}

解决方案2

data class Hour private constructor (val value: Int) {

    companion object {
       operator fun invoke(hour: Int) =
           when {
               hour >= 24 || hour < 0 -> throw IllegalArgumentException(
                   "Invalid hour value. Hour must be within the range of 0 to 23."
               )
               else -> Hour(hour)
           }
    }
}

data class Minute private constructor(val value: Int) {

    companion object {
        operator fun invoke(minute: Int) =
            when {
                minute >= 60 || minute < 0 -> throw IllegalArgumentException(
                    "Invalid minute value. Minute must be within the range of 0 to 59."
                )
                else -> Minute(minute)
            }
    }
}

data class CombinedMinutes(val value: Int) {

    fun getHour(): Hour = Hour(this.value / 60)
    fun getMinute(): Minute = Minute(this.value % 60)

    companion object {
        private const val MAX_COMBINED_MINUTES = 1439 // 23 * 60 + 59

        operator fun invoke(combinedMinutes: Int) =
            when {
                combinedMinutes > MAX_COMBINED_MINUTES || combinedMinutes < 0 ->
                    throw IllegalArgumentException(
                        "Invalid combined minutes value. " +
                                "Combined minutes must be within the range of 0 to 1439"
                    )
                else -> CombinedMinutes(combinedMinutes)
            }

        operator fun invoke(hour: Hour, minute: Minute) =
            CombinedMinutes(hour.value * 60 + minute.value)
    }
}

data class AlamTime2 private constructor(val hour: Hour, val minute: Minute) {
    companion object {
        operator fun invoke(hour: Hour, minute: Minute) =
            AlamTime2(hour, minute)

        operator fun invoke(combinedMinutes: CombinedMinutes) =
            AlamTime2(combinedMinutes.getHour(), combinedMinutes.getMinute())
    }
}
kotlin model functional-programming architecture clean-architecture
1个回答
0
投票

我想挑战你的前提,即数据类非常适合你想要做的事情。

虽然没有明确说明,但从您的代码来看,您似乎希望确保无法创建无效的

AlarmTime
。 这不适用于数据类,因为您免费获得的功能之一是 copy 函数,它强制执行值的类型,但不强制验证。特别是以下编译和运行:

AlarmTime(12,30).copy(minute = -1)
  .also { println(it) } // AlarmTime(hour=12, minute=-1)
© www.soinside.com 2019 - 2024. All rights reserved.