Kotlin一般性问题,UNCHECKED_CAST,必需:无

axkjgtzd  于 2023-02-16  发布在  Kotlin
关注(0)|答案(1)|浏览(309)
@file:Suppress("UNCHECKED_CAST")

data class Element<T>(
    val key: String,
    val valueOne: T,
    val valueTwo: T,
    val comparator: Comparator<T>,
    val comparatorValue: CompareResult
)

enum class CompareResult(
    val value: Int
) {
    LESS(-1),
    EQUAL(0),
    GREATER_THAN(1)
}

fun <T> matchesComparison(list:Collection<Element<T>>): Pair<Boolean, List<String>> {
    val failedComparisons = mutableListOf<String>()
    for (element in list) {
        val compareValue = element.comparator.compare(element.valueOne, element.valueTwo)
        if (element.comparatorValue.value != compareValue) {
            failedComparisons.add(element.key)
        }
    }
    return Pair(failedComparisons.isEmpty(), failedComparisons)
}

val stringComparator = Comparator.comparing(String::toString)
val intComparator = Comparator.comparing(Int::toInt)

val elementsToCompare = listOf(
    Element("number", 1, 2, intComparator, CompareResult.LESS),
    Element("first name", "a", "a", stringComparator, CompareResult.EQUAL),
    Element("last name", "a", "b", stringComparator, CompareResult.EQUAL)
)

matchesComparison(elementsToCompare).second.joinToString(", ","Failed elements: \"","\"")

我经常面临比较两个具有相同值的不同对象属性的问题。例如,对象A具有props number,firstname,lastname.我想做的是创建一个列表have和have函数来遍历这些元素并返回哪些 prop 没有通过比较,我已经设法为对象和matchesComparison函数使用了泛型,matchesComparison函数返回失败的比较。当我想把这个类型为Collection〈Element〈out Any〉〉的列表传递给这个函数时,问题就开始了,我得到了一个类型missmatch。与其使用未检查的强制转换来强制比较器为Any类型,我宁愿这样做

val stringComparator = Comparator.comparing(String::toString) 
val intComparator = Comparator.comparing(Int::toInt)

上述脚本的结果值应为Failed elements: "last name"
我尝试将函数的签名改为out any,但是comparator.compare方法的两个参数都是Nothing类型。我真的希望避免取消未检查的强制转换。

42fyovps

42fyovps1#

matchesComparison()在这里不需要是泛型的,它并不关心整个输入集合的类型,所以我们可以简单地使用*
然后我们还有另一个问题。编译器不够聪明,没有注意到当我们在单个元素上执行操作时,它的所有属性都是匹配类型。因此,它不允许在element.valueOneelement.valueTwo上使用element.comparator。要解决这个问题,我们只需要创建一个单独的函数,它可以在单个Element上工作。因此它理解所有属性的类型是相同的:

fun matchesComparison(list:Collection<Element<*>>): Pair<Boolean, List<String>> {
    fun <T> Element<T>.matches() = comparatorValue.value == comparator.compare(valueOne, valueTwo)

    val failedComparisons = mutableListOf<String>()
    for (element in list) {
        if (!element.matches()) {
            failedComparisons.add(element.key)
        }
    }
    return Pair(failedComparisons.isEmpty(), failedComparisons)
}

另外,我相信这样的matches()函数实际上应该是Element的成员函数。奇怪的是,虽然Element是相当独立的,它包含了执行比较所需的一切,它仍然需要使用外部代码,如果它有一个matches()函数,那么我们就不需要关心它的Tmatches()将与任何Element一起工作。

相关问题