这个问题是要弄清楚语言是否有可能,而不是特定的问题或案例。
我还在学习Kotlin的动态性和功能性。
有没有办法扭转这个:
for (item in myList) item.someMethod()
变成这样的东西:
myList.all().someMethod()
鉴于:
data class MyObj(val v: String) {
fun someMethod() {
println(v)
}
}
val myList = listOf(MyObj("A"), MyObj("B"), MyObj("C"))
for (item in myList) item.someMethod()
你可以这样做:
fun List<MyObj>.someMethod() {
for (e in this) {
e.someMethod()
}
}
fun List<MyObj>.all() = this
它是特定类型列表上的简单扩展函数。
如果你需要像动态调度那样的想法,那就不可能了。
但也许你需要的是一个复合设计模式,其中容器和元素都实现相同的接口。像这样的东西:
interface SomeInterface {
fun someMethod()
}
class MyList(val elements: List<MyObj>) : SomeInterface {
override fun someMethod() {
for (e in elements) {
e.someMethod()
}
}
}
data class MyObj(val v: String) : SomeInterface{
override fun someMethod() {
println(v)
}
}
将类似地工作:
val myList = MyList(listOf(MyObj("A"), MyObj("B"), MyObj("C")))
myList.someMethod()
这种模式在元素集合和单个元素之间提供了一个很好的契约。
保持简单。
myList.forEach { it.someMethod() }
// or
myList.forEach(Item::someMethod)
扩展功能也是可能的,但也许已经太多了(至少缩小到你的类型):
fun List<Item>.someMethod() = forEach { it.someMethod() }
或者,如果要根据特定接收器访问该方法,还可以在该特定类型中声明扩展函数。所以给定一个类型为MyObj
的扩展函数如下:
class MyObj {
val funnyItems = mutableListOf<Item>()
val usefulItems = mutableListOf<Item>()
val whateverItems = mutableListOf<Item>()
fun List<Item>.someMethod() = forEach { it.someMethod() }
}
如果你有适当的接收器,它只能被调用。因此,如下所示在类MyObj
中添加一个函数,有效:
fun callingSomeMethod() = funnyItems.someMethod() // no problem
但不会在MyObj
之外工作。例如。考虑不在main
内的MyObj
方法:
fun main(args: Array<String>) {
listOf(MyObj())
.forEach {
// the following will not work... it is not accessible without appropriate receiver
// it.funnyItems.someMethod() // doesn't compile...
with(it) {
// 'this' is now MyObj which is the required receiver in addition to List<Item>, so the following works:
this.funnyItems.someMethod()
}
}
}