简体   繁体   English

仅当输入不为null时才如何使用kotlin的默认参数?

[英]How to use kotlin's default parameter only if the input is not null?

Example: 例:

data class Something(val mendatory: String = "default value")

val userInput: String? by SomeTypeOfInputFieldThatReturnsNullable

//val something = Something(userInput)    //not valid because userInput is String?

val something = if (userInput == null) 
                    Something() 
                else 
                    Something(userInput)

Is there some less verbose way to tell kotlin to only pass parameter if it's not null? 是否有一些更简单的方法告诉Kotlin仅在不为null时传递参数?

Depends on what you mean by less verbose. 取决于您的意思,而不是冗长。

One way is using the null-safe-operator ( ?. ) and something like let : 一种方法是使用null-safe-operator( ?.和诸如let东西:

val something = userInput?.let(::Something) 
                         ?: Something()

I leave it up to you whether this is really less verbose. 我是否要那么冗长取决于您自己。

Another variant is to basically just pass the null -value up to the data class . 另一个变体是基本上只将null值传递给data class Either by providing appropriate constructors or by having appropriate factory functions in place. 通过提供适当的构造函数或适当的工厂功能。 The following is just one of many variants (now using Companion and invoke ): 以下只是众多变体之一(现在使用Companioninvoke ):

data class Something(val mandatory: String) {
  companion object {
    operator fun invoke(s : String? = null) = Something( s ?: "default value")
  }
}

Calling it then looks like: 然后调用它看起来像:

val something = Something(userInput) // if userInput is String? the companion function is called... if it's String, the constructor is used

// or also using invoke:
val something = Something() // now with s = null, leading to "default value"

I can think of a few approaches, but all of them involve repetition somewhere… 我可以想到几种方法,但是所有方法都涉及到重复某处…

If this was the only place you needed the default value, you could move it out of the class: 如果这是唯一需要默认值的地方,则可以将其移出类:

data class Something(val mandatory: String)

val something = Something(userInput ?: "default value")

Or you could allow the constructor to take a null — but then you'd need to separate the nullable constructor param from the non-null property: 或者,您可以允许构造函数采用null-但随后您需要将可为null的构造函数参数与non-null属性分开:

data class Something(mandatoryParam: String?) {
    val mandatory = mandatoryParam ?: "default value"
}

val something = Something(userInput)

Or there are the options Roland outlined in his answer: use let to avoid some of the repetition when deciding which constructor to call; 或者,Roland在他的答案中列出了一些选择:在确定要调用的构造函数时,请使用let避免重复。 or using a pseudo-constructor on the companion object. 或在随播对象上使用伪构造函数。

So, no single obvious answer. 因此,没有一个明显的答案。 (I think I'd probably prefer one of the two approaches I've illustrated, depending whether the default value relates in any way to this particular user input, or whether it must necessarily apply however the object gets constructed.) (我认为我可能更喜欢上面介绍的两种方法之一,这取决于默认值是否以某种方式与该特定用户输入相关,或者无论构造对象时该默认值是否必须一定都适用。)

There are many solutions that the other have explained... The best one is: 另一个解释了许多解决方案……最好的解决方案是:

val something = userInput?.let(::Something) ?: Something()

But there is another way too, if you change 'val' to 'var': 但是,如果将“ val”更改为“ var”,那么还有另一种方法:

data class Something(var mendatory: String = "default value")

val userInput: String? by SomeTypeOfInputFieldThatReturnsNullable

val something = Something().apply { userInput?.let { mendatory = userInput } }

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM