提问人:Merlin -they-them- 提问时间:7/15/2023 更新时间:7/15/2023 访问量:42
如何获得具有任何 -> Unit 的 lambda 表达式以匹配具有不同枚举 -> Unit 的多个 lambda?
How to get a lambda expression with Any -> Unit to match multiple lambdas with different enum -> Unit?
问:
我创建了一个 Dropdown 可组合项,我想将其用于不同的枚举列表。为此,Dropdown 接受一个 onValueChange 参数,该参数是具有 Any 类型的 lambda 函数。
我第一次尝试使用一种类型,我收到了 .onValueChange
(Any) -> Unit
Type mismatch. Required: (Any) -> Unit. Found: (Color) -> Unit
然后我使用并得到了同样的东西.typealias Callback<T> = (T) -> Unit
Type mismatch. Required: Callback<Any>. Found: Callback<Color>
如果我将 lambda 转换为 或 ,我会收到警告。我可以禁止显示此警告,但我宁愿以“正确”的方式修复它。(Any) -> Unit
Callback<Any>
Unchecked cast
如果我将类型设置为 ,则在调用 Dropdown 时不再出现类型错误,但 Dropdown 的内部调用现在有onValueChange
Callback<*>
onValueChange
Type mismatch with Callback<*>. Required: Nothing. Found: Any
- 如何在没有类型不匹配和未检查的强制转换警告的情况下使它工作?
- 为什么 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
}
)
}
}
}
}
答:
你的代码在概念上是错误的,它不是类型安全的——这就是 Kotlin 不允许它的原因。
在你有一个 lambda 中,它接收一个,它只能处理颜色。然后你想把它转换为 ,所以 转换为可以接收任意对象的 lambda。如果我们随后通过传递 String 或 Int 来调用它怎么办?ColorDropdown
Color
(Any) -> Unit
如果您的想法是 lambda 总是接收传入的项目之一,那么您必须使您的函数泛型:options
fun <T> Dropdown(value: T, options: List<T>, onValueChange: Callback<T>) {
评论