如何获得具有任何 -> Unit 的 lambda 表达式以匹配具有不同枚举 -> Unit 的多个 lambda?

How to get a lambda expression with Any -> Unit to match multiple lambdas with different enum -> Unit?

提问人:Merlin -they-them- 提问时间:7/15/2023 更新时间:7/15/2023 访问量:42

问:

我创建了一个 Dropdown 可组合项,我想将其用于不同的枚举列表。为此,Dropdown 接受一个 onValueChange 参数,该参数是具有 Any 类型的 lambda 函数。

我第一次尝试使用一种类型,我收到了 .onValueChange(Any) -> UnitType mismatch. Required: (Any) -> Unit. Found: (Color) -> Unit

然后我使用并得到了同样的东西.typealias Callback<T> = (T) -> UnitType mismatch. Required: Callback<Any>. Found: Callback<Color>

如果我将 lambda 转换为 或 ,我会收到警告。我可以禁止显示此警告,但我宁愿以“正确”的方式修复它。(Any) -> UnitCallback<Any>Unchecked cast

如果我将类型设置为 ,则在调用 Dropdown 时不再出现类型错误,但 Dropdown 的内部调用现在有onValueChangeCallback<*>onValueChangeType mismatch with Callback<*>. Required: Nothing. Found: Any

  1. 如何在没有类型不匹配和未检查的强制转换警告的情况下使它工作?
  2. 为什么 Kotlin 不认为具有特定类型化参数的 lambda 是具有 Any 参数的 lambda?像这样的事情不就是 Any 的全部意义吗?

示例用法

@Composable
fun ColorDropdown(color: Color, onColorChange: (Color) -> Unit) {
    val colorOptions = listOf(Color.BLACK, Color.GRAYSCALE, Color.WHITE, Color.MONOCHROME)
    // Type mismatch
    Dropdown(color, options = colorOptions, onValueChange = onColorChange)
}

fun AlignDropdown(color: Align, onAlignChange: Callback<Align>) {
    val alignOptions = listOf(Align.LEFT, Align.CENTER, Align.RIGHT)
    // Unchecked cast
    Dropdown(color, options = colorOptions, onValueChange = onAlignChange as Callback<Any>)
}

下拉列表文件

typealias Callback<T> = (T) -> Unit

@Composable
fun Dropdown(value: Any, options: List<Any>, onValueChange: Callback<Any>) {
    var expanded by remember { mutableStateOf(false) }

    Box {
        Button( onClick = { expanded = !expanded } ) { Text("Color: $value") }
        DropdownMenu( expanded = expanded, onDismissRequest = { expanded = false } ) {
            options.forEach { option ->
                DropdownMenuItem(
                    text = { Text(option.toString()) },
                    onClick = {
                        // Type mismatch with Callback<*>
                        // Required: Nothing. Found: Any.
                        onValueChange(option)
                        expanded = false
                    }
                )
            }
        }
    }
}
Android Kotlin Lambda 类型 转换

评论


答:

3赞 broot 7/15/2023 #1

你的代码在概念上是错误的,它不是类型安全的——这就是 Kotlin 不允许它的原因。

在你有一个 lambda 中,它接收一个,它只能处理颜色。然后你想把它转换为 ,所以 转换为可以接收任意对象的 lambda。如果我们随后通过传递 String 或 Int 来调用它怎么办?ColorDropdownColor(Any) -> Unit

如果您的想法是 lambda 总是接收传入的项目之一,那么您必须使您的函数泛型:options

fun <T> Dropdown(value: T, options: List<T>, onValueChange: Callback<T>) {

评论

0赞 Merlin -they-them- 7/16/2023
谢谢!这解决了我所有的问题。我是积极使用类型的新手,所以这是我还没有学到的东西