kotlin 如何将Unit和Nothing结合起来?

dbf7pr2w  于 2022-11-16  发布在  Kotlin
关注(0)|答案(1)|浏览(168)

我想禁用一个setter。因此我把它标记为private,它唯一做的就是抛出一个异常。

private val authorization = object {
    val header = "Authorization"
    var granted: Boolean = false
        set (value) {
            field = value
            if (granted)
                preferences.save (username, password)
            else
                recalc_basicauth = true }
    var username: String = ""
        set (value) {
            granted = false
            field = value }
    var password: String = ""
        set (value) {
            granted = false
            field = value }
    private var recalc_basicauth = true
    private val basicauth_prefix = "Basic "
    var basicauth: String = basicauth_prefix
        get() {
            if (recalc_basicauth) {
                field = basicauth_prefix + Base64.getEncoder()
                    .encodeToString ("$username:$password".toByteArray())
                recalc_basicauth = false }
            return field }
        private set (value) : Nothing {
            throw IllegalArgumentException ("basicauth must not set directly") } }

一个永远不会返回的函数应该有Nothing的返回值,但是setter必须有Unit的返回值。
有没有办法把两者结合起来呢?

wz3gfoph

wz3gfoph1#

规范中规定setter返回类型必须为Unit类型:
如前所述,属性声明可以包括自定义getter和/或自定义setter(统称为访问器),其形式为

var x: T = e
    get(): TG { ... }
    set(anyValidArgumentName: TS): RT { ... }

这些函数具有以下要求

  • ...
  • RT ≡Kotlin,单位;
  • ...

你不必显式地将setter标记为返回Nothing

private set (value) = 
    throw IllegalArgumentException ("basicauth must not set directly")

setter将被声明为返回Unit,但是您唯一没有得到的是Nothing附带的控制流和数据流分析,就像当您执行以下操作时友好的“不可达代码”警告:

basicauth = ""
println("Foo") // you don't get an unreachable code warning here

或者是Kotlin所做的智能零分析:

if (something == null) { basicAuth = "" }
// safely use something, because an exception would have been thrown

但坦率地说,上面的例子是相当愚蠢的。我怀疑任何人会写这样的代码,并期望它的工作
或者,您可以加入其他属性来停用setter:

private var basicAuthCache: String = basicauth_prefix

val basicauth: String
    get() {
        if (recalc_basicauth) {
            basicAuthCache = basicauth_prefix + Base64.getEncoder()
                .encodeToString ("$username:$password".toByteArray())
            recalc_basicauth = false
        }
        return basicAuthCache
    }

相关问题