访问字符串模板中可为空的属性时如何避免打印“null”?

问题描述 投票:0回答:3

我有一个 Person 类,其爱好属性可为空。当我尝试使用字符串模板打印此人的个人资料时,如果爱好为空,它会打印“空”。

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}”,它无法按预期工作。

为什么我不能在 getReferrerName 中传递 getHobby 来处理推荐人爱好的 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 .

如果推荐人的爱好不为空,则输出应包含它:

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 .

临时解决方案:

我通过在 getReferrerName 中添加 if/else 检查来实现临时解决方案

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 的更优雅的解决方案。

kotlin google-codelab
3个回答
2
投票

您不能在

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)}" )
}

1
投票

您遇到此 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)}" )

然后你将得到以下输出

enter image description here


1
投票

为什么我不能在其中传递 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)}" )
}
© www.soinside.com 2019 - 2024. All rights reserved.