我想將屬性 getter 方法參考作為函式引數之一傳遞,并讓該引數屬于我自己的函式介面型別,但遇到了問題。
這是一個精簡的最小可重現案例,我將變數從引數更改為屬性,但問題是一樣的。
class Foo {
val bar: Bar? = null
}
class Bar
fun interface FooBarSelector {
fun select(foo: Foo): Bar?
}
class KotlinClass() {
val selector: FooBarSelector = Foo::bar
}
這不編譯,Foo::bar帶下劃線,錯誤是
Type mismatch.
Required: FooBarSelector
Found: KProperty1<Foo, Bar?>
我試著查了一下,發現了關于 SAM 轉換的類似問題,但它們有點不同,我認為它們中的任何一個都沒有專門針對屬性獲取器。
我發現可以通過執行以下操作之一來解決該問題:
- 洗掉顯式型別,或將其替換為建議的
KProperty1. 不是一個選項,我想保留我的型別。 - 將方法參考替換為
FooBarSelector { it.bar }. 遠非理想,但比第一種選擇更好。
為什么會發生這種情況,還有其他選擇嗎?我是 Kotlin 的新手,但不是 Java。
使用的 Kotlin 版本是 1.7.20
編輯:
這是我最初的目標:接受 aFooBarSelector作為引數,并默認將其指向屬性 getter:
fun doSomething(
selector: FooBarSelector = Foo::bar //doesn't compile
) {
}
uj5u.com熱心網友回復:
您的 lambda 代碼很好,但您可能更喜歡這種語法來做同樣的事情:
class KotlinClass() {
val selector = FooBarSelector(Foo::bar)
}
解釋:
Kotlin 函式參考比 Java 中的型別更明確,因為函式參考是一流的物件型別。當您想將函式參考用作功能介面實體時,您必須對其進行轉換。這可以由編譯器使用 SAM 轉換自動完成。
SAM 轉換僅在將函式參考作為引數傳遞給具有函式介面型別的引數的函式時才有效。因此,它在分配給屬性時不會直接起作用。
但是 Kotlin 隱含地為函式式介面提供了更高階的函式,允許您傳遞將其轉換為介面實體的函式參考。隱式函式以介面命名,因此看起來像建構式呼叫。
在上面的代碼中,隱式函式介面“建構式”是inline,所以編譯后的代碼中沒有分配中間函式物件。這與您在 Java 中通過直接方法參考獲得的內容相同。
uj5u.com熱心網友回復:
我不是 100% 確定您的期望,但請考慮以下示例:
class Foo(
val bar: Bar
)
data class Bar(
val value: String
)
interface FooBarSelector {
fun select(foo: Foo): Bar {
return foo.bar
}
}
class FooBarCustomSelector: FooBarSelector {
override fun select(foo: Foo): Bar {
return Bar("I don't care about which Foo was passed. I'll return my own Bar")
}
}
class KotlinClass(val selector: (Foo) -> Bar = Foo::bar)
fun main(args: Array<String>) {
val kotlinClassWithDefaultSelector = KotlinClass()
val kotlinClassWithCustomSelector = KotlinClass(FooBarCustomSelector()::select)
val foo = Foo(Bar("Bar1"))
println("kotlinClassWithDefaultSelector: ${kotlinClassWithDefaultSelector.selector(foo)}")
println("kotlinClassWithCustomSelector: ${kotlinClassWithCustomSelector.selector(foo)}")
}
這將列印:
kotlinClassWithDefaultSelector: Bar(value=Bar1)
kotlinClassWithCustomSelector: Bar(value=I don't care about which Foo was passed. I'll return my own Bar)
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/529187.html
