嵌套安全调用空检查Kotlin
我需要在ImageView中显示图像,因此首先需要确保图像url不为null。这3个选项有效吗 回答数据类嵌套安全调用空检查Kotlin,kotlin,Kotlin,我需要在ImageView中显示图像,因此首先需要确保图像url不为null。这3个选项有效吗 回答数据类 data class Answer( val id: Long?, val title: String?, val answerImage: AnswerImage? ) { data class AnswerImage( val x0: AnswerImageData?, val x1: AnswerImageData?,
data class Answer(
val id: Long?,
val title: String?,
val answerImage: AnswerImage?
) {
data class AnswerImage(
val x0: AnswerImageData?,
val x1: AnswerImageData?,
val x2: AnswerImageData?
) {
data class AnswerImageData(
val id: String?,
val url: String?
)
}
}
选项1
answer.answerImage?.let { answerImage ->
answerImage.x0?.let { answerImageData ->
answerImageData.url?.let {
//display image
}
}
}
选项2
if (answer.answerImage?.x0?.url != null)
{
//display image
}
选项3
answer.answerImage?.x0?.url?.let {
//display image
}
简短回答:是的
- 选项1:如果您确实需要使用
和answerImage
执行更多操作,而不仅仅是安全地将其投射,那么这将是一个不错的选择。在这种特定情况下,我们不需要显式声明这些变量。总结:在这种情况下,选项1不是一个很好的解决方案,但它确实有效answerImageData
- 选项2:应该有效,因为所有属性都是不可变的。然后,编译器可以在下一行(在
范围内)推断if
属性仍然是非url
null
- 选项3:我认为这是最好的一个:作为代码的读取器,这是最容易处理的一个,因为您通常会用这样的代码来完成它:
。让{safeUrl->..}
fun尝试显示图像(答案:答案){
val answerImage=answer.answerImage?:返回
val answerImageData=answerImage.x0?:返回
val answerImageDataUrl=answerImageData.url?:返回
//显示图像
}
有一篇关于这个主题的有趣文章Ken给出了答案(他们都很好,做了同样的事情,最后一篇是如何设计语言来真正、漂亮、整洁地使用!),但我想谈谈实际的数据模型
首先,您说需要检查AnswerImageData
的url
是否为空。但是它可以为null的唯一原因是,您使用String?
type显式地将它设置为null。带有空url
的AnswerImageData
是否有效?还是它总是需要有一个?我猜是的,而且我猜它也总是需要一个id
,所以只需将它们设置为非null
data class AnswerImageData(
val id: String,
val url: String
)
现在,您的所有AnswerImageData
对象都保证具有非空值——从这个意义上说,它们都是有效的,这已经融入到您的设计中。所以你不再需要对它们进行空检查了
你的其他类也是一样——你能有一个带有空值的AnswerImage
?这可能是一个更棘手的问题,让我们假设在AnswerImage
中需要始终至少有一个AnswerImageData-在这种情况下,可以将第一个设置为非空,其他设置为可选:
data class AnswerImage(
val x0: AnswerImageData,
val x1: AnswerImageData?,
val x2: AnswerImageData?
)
这不一定是最好的方法-我个人更喜欢vararg
参数,或者某种类型的集合,这样您就可以拥有任意数量的AnswerImageData
s,并执行.first(predicate)
之类的操作来轻松地循环它们。但是如果你想要三个插槽,三个参数就是一种方法
Answer
-我猜这需要一个id
,title
和answerImage
-如果是这样,不要让它们为空。通过您的类型强制执行有效的结构,这将使您的生活更加轻松!避免可为空的类型也是如此,除非您确实需要它们
我不知道这是否适用于你正在做的事情,但它可能适用,所以值得一提。(如果你想研究的话,这类东西叫做*域驱动设计-基本上通过设计代码、类型、对象等的方式强制执行业务逻辑的规则和结构)以上所有答案都很好,但我想提一点。您将属性声明为可空,所以我猜您是从其他地方(如果您熟悉clean体系结构,那么可以从数据层)获取它们的 我的建议是为类创建一个域模型,并将数据映射到域模型(具有非空属性)。这样可以在映射器中处理空值。它更干净,遵循关注点分离和单一责任原则
interface Mapper<F, S> {
fun firstToSecond(first: F): S
fun secondToFirst(second: S): F
}
类DataToDomainMapper:Mapper{
覆盖乐趣第一到第二(第一:数据模型):DomainModel{
返回域模型(
id=first.id?:-1,
title=first.title?:“无标题”,
answerImage=first.answerImage?:answerImage()
)
}
覆盖乐趣secondToFirst(第二个:DomainModel):数据模型{
返回数据模型(
id=second.id,
title=second.title,
answerImage=second.answerImage
)
}
}
这样,您就不必在代码中的任何其他地方处理null。对于数据验证,您可以检查id是否为负值。我缩短了你的模型,但你明白了他们编译吗?他们是否正确地检查空值?对那么它们是有效的。这是你可以自己轻松测试的东西。谢谢。然后我将使用选项3。我将AnswerImageData的url设置为null,因为这是我从一个Rest API获得的数据,我不拥有该API,并且没有太多关于其实现的信息,所以我假设它可以为null。这是一个示例请求,假设您返回了一个空url,那么这仍然是您想要保留的有效的
AnswerImageData
(或其他)吗?或者它是无效的,你不打算使用的东西?您可以使用一个函数来获取API响应,验证它,并创建一个AnswerImageData
if(且仅当!)它具有您需要的所有数据。这样,您只需要创建有效的对象,因此,如果您理解的话,该类不需要能够表示无效状态。所以现在你再也不用担心如何处理它了。我不知道你到底在做什么,也不知道你是否需要保留它们,但这可能会有所帮助!这个我
data class DataModel(
val id: Long?,
val title: String?,
val answerImage: AnswerImage?
)
data class DomainModel(
val id: Long,
val title: String,
val answerImage: AnswerImage
)
class DataToDomainMapper: Mapper<DataModel, DomainModel> {
override fun firstToSecond(first: DataModel): DomainModel {
return DomainModel(
id = first.id ?: -1,
title = first.title ?: "no title",
answerImage = first.answerImage ?: AnswerImage()
)
}
override fun secondToFirst(second: DomainModel): DataModel {
return DataModel(
id = second.id,
title = second.title,
answerImage = second.answerImage
)
}
}