我有一个 Person 类,其爱好属性可为空。当我尝试使用字符串模板打印此人的个人资料时,如果爱好为空,它会打印“
null
”。
fun main() {
val amanda = Person("Amanda", 33, null, null)
val atiqah = Person("Atiqah", 28, "climb", amanda)
amanda.showProfile()
atiqah.showProfile()
}
class Person(val name: String, val age: Int, val hobby: String?, val referrer: Person?) {
fun showProfile() {
val getReferrerName: (Person?) -> String = {
if (it != null) "Has a referrer named ${it.name} who likes to ${it.hobby} ."
else "Doesn't have a referrer."
}
val getHobby: (String?) -> String = {
if (it != null) "likes to $it"
else "."
}
println("Name: ${name}\nAge: $age\n ${getHobby(hobby)} ${getReferrerName(referrer)}")
}
}
例如,如果推荐人的爱好为空,则输出为:
Name: Amanda
Age: 33
. Doesn't have a referrer.
Name: Atiqah
Age: 28
likes to climb Has a referrer named Amanda who likes to null .
我的具体问题
我有一个 lambda
getHobby
来处理 hobby 属性的 null 情况。但是,当我尝试在另一个 lambda getReferrerName
中使用它时,如下所示:“ who likes to ${getHobby}
”,它无法按预期工作。
为什么我不能在
getHobby
中传递 getReferrerName
来处理推荐人爱好的 null 情况?
我知道有更简单的方法可以使用
if/else
语句来解决这个问题,但我正在学习 lambda 并希望找到使用它们的解决方案。
如果推荐人的爱好为空,则输出应打印
.
所需输出:
Name: Amanda
Age: 33
. Doesn't have a referrer.
Name: Atiqah
Age: 28
likes to climb Has a referrer named Amanda .
如果推荐人的爱好不是
null
,则输出应包含它:
Name: Amanda
Age: 33
likes to run Doesn't have a referrer.
Name: Atiqah
Age: 28
likes to climb Has a referrer named Amanda who likes to run .
临时解决方案:
我通过在
if/else
中添加
getReferrerName
检查来实现临时解决方案
val getReferrerName: (Person?) -> String = {
if (it != null) "Has a referrer named ${it.name} ${if(it.hobby !=null) "who likes to ${it.hobby}" else ' '} ."
else "Doesn't have a referrer."
}
但是,如果可能的话,我更喜欢使用 lambda 的更优雅的解决方案。
您不能在
getHobby
的第一行内使用 showProfile()
,因为此时 getHobby
尚未定义。
如果您首先定义
getHobby
(或者更好,作为 Person
的类成员或 Person
上的扩展函数,但您想使用 lambda),那么在 getHobby
定义中使用 getReferrerName
不会有任何问题:
fun showProfile() {
val getHobby:(String?)-> String={ if (it != null)"likes to $it" else "."}
val getReffererName: (Person?) -> String = { if (it != null) "Has a referrer named ${it.name} who likes to ${getHobby(it.hobby)} ." else "Doesn't have a referrer." }
println("Name: ${name}\nAge: $age\n ${getHobby(hobby)} ${getReffererName(referrerr)}" )
}
您遇到此 null 问题是因为您在调用
getReffererName
时处理了 null。
//here you directly used ${it.hobby}
val getReffererName: (Person?) -> String = { if (it != null) "Has a referrer named ${it.name} who likes to ${it.hobby} ." else "Doesn't have a referrer." }
所以你应该首先声明
getHobbies
和 getreffererName
并且你必须使用你的函数来处理 null 即 getHobbies
。
val getHobby:(String?)-> String={ if (it != null)"likes to $it" else "."}
val getReffererName: (Person?) -> String = { if (it != null) "Has a referrer named ${it.name} who likes to ${getHobby(it.hobby)} ." else "Doesn't have a referrer." }
println("Name: ${name}\nAge: $age\n ${getHobby(hobby)} ${getReffererName(referrerr)}" )
然后你将得到以下输出。
为什么我不能在其中传递 getHobby 即“谁喜欢 ${getHobby}”,因为它已经处理了 null 情况?
好吧,你可以写一个电话给
getHobby
——只需先声明getHobby
。然后你就可以写${getHobby(it.hobby)}
。
val getHobby:(String?) -> String = { if (it != null)"likes to $it" else "." }
val getReffererName: (Person?) -> String = { if (it != null) "Has a referrer named ${it.name} who likes to ${getHobby(it.hobby)} ." else "Doesn't have a referrer." }
但它不会产生所需的输出。当
hobby
不为空时,会产生两次“喜欢”,例如
likes to climb Has a referrer named Amanda who likes to likes to run .
当
.
为空时,这也会产生两个 hobby
字符,如果我理解正确的话,这是不可取的。
归根结底,
getHobby
的逻辑根本就不太可重用,因为您希望以一种适合个人爱好的方式格式化爱好(.
为空时,以及“喜欢”前缀) ,但以另一种方式满足推荐人的爱好(null 时为空字符串,以及“who likes to”前缀)。所有的共同点都是“喜欢”部分。如果你想重复使用它,你可以这样做:
private val hobbyDescription get() = hobby?.let { "likes to $it" }
private val referrerDescription get() = referrer?.let {
val hobbyDescription = it.hobbyDescription?.let { " who $it" } ?: ""
"Has a referrer named ${it.name}$hobbyDescription ."
}
fun showProfile() {
println("Name: ${name}\nAge: $age\n ${hobbyDescription ?: "."} ${referrerDescription ?: "Doesn't have a referrer."}" )
}
请注意,我对爱好和引用者私有属性进行了描述,而不是对函数类型的本地
val
进行了描述,因为这对我来说更有意义。如果你喜欢自己的风格,你可以这样做:
fun showProfile() {
val getHobby:(String?) -> String? = {
if (it != null) "likes to $it" else null
}
val getReferrerName: (Person?) -> String = {
val hobbyDescription = getHobby(it?.hobby)?.let { " who $it" } ?: ""
if (it != null) "Has a referrer named ${it.name}$hobbyDescription ."
else "Doesn't have a referrer."
}
println("Name: ${name}\nAge: $age\n ${getHobby(hobby) ?: "."} ${getReferrerName(referrer)}" )
}