【问题标题】:Kotlin: Upcast and sealed classesKotlin:Upcast 和密封类
【发布时间】:2016-01-24 14:17:12
【问题描述】:

我正在使用 FunKTionale 库来执行模式匹配。然后,当我如下初始化一个变量时:

private lateinit var socket = Option.None 

下面的转换是不可能的:

socket = socket.map {
    selectedDevice.createRfcommSocketToServiceRecord(MY_UUID).apply {
    connect()
    }
}

因为socket的类型是

Option.None

但是如果我将套接字变量初始化为

private lateinit var socket: Option<BluetoothSocket> = Option.None    

地图功能有效。 Option.None 对象扩展

Option<Nothing>

并被强制转换为(在这种情况下)

Option<BluetoothSocket>

那么,这怎么可能呢?

【问题讨论】:

    标签: kotlin


    【解决方案1】:

    原因是当你省略字段类型时,最具体的类型是从初始值类型推断出来的。要声明具有某种不太具体的类型的字段,应明确指定它。

    假设在您的情况下层次结构如下所示:

    Any -> ... -> Option -> Option.None
    

    所以,当初始值的类型为Option.None时,它也会被推断为字段类型,并且该字段将无法存储更通用类型Option的值。

    要使字段类型Option 或更通用的类型达到Any,您必须明确指定它。

    为了更清楚,这也应该适用于您的情况:

    var socket = Option.None as Option<Socket>
    

    这里,Option.None as Option&lt;Socket&gt; 的类型不是Option.None,而是Option。 但是,当您在复杂的层次结构情况下指定字段的类型时,代码更具可读性。

    【讨论】:

    • 我明白了,但是如何将 Option(这是 Option.None 的类型)转换为 Option
    • @JulysPablo,它在类型系统中:正如Any 是任何其他(不可为空)类型的超类型,Nothing 是任何其他类型的子类型。据此,示例代码有效:val lst: List&lt;Int&gt; = listOf&lt;Nothing&gt;()。例如,throw 表达式的类型为 Nothing
    • 谢谢@hotkey。我不知道 Nothing 是任何其他类型的子类型
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2021-12-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2013-04-19
    • 1970-01-01
    相关资源
    最近更新 更多