Kotlin中的类型安全性无法按预期工作

时间:2018-06-07 10:27:29

标签: kotlin

我有这样的代码:

enum class Player { PLAYER, COMPUTER }

interface BoardCell {
    val x: Int
    val y: Int
    var player: Player?
}

data class Cell(val x: Int, val y: Int, var player: Player?, var value: Int)
data class BoardCellClass(override val x: Int, override val y: Int, override var player: Player?) : BoardCell
data class Request(val board: MutableList<MutableList<BoardCellClass>>? = null, val occupied: MutableList<BoardCellClass>? = null)

class AI(board: MutableList<MutableList<BoardCell>>, private var occupied: MutableList<BoardCell>) {
    private var board: MutableList<MutableList<Cell>> = board.map { it.map { Cell(it.x, it.y, it.player, 0) } .toMutableList() } .toMutableList()
}

// in main

val request = call.receive<Request>()

if (request.board == null || request.occupied == null) {
    // respond with 403
} else {
    val ai = AI(request.board, request.occupied) // Kotlin: Type mismatch: inferred type is MutableList<MutableList<BoardCellClass>>? but MutableList<MutableList<BoardCell>> was expected
                                                 // Kotlin: Type mismatch: inferred type is MutableList<BoardCellClass>? but MutableList<BoardCell> was expected
}

但它与底部评论中的内容有误。我究竟做错了什么?显然,有一个if语句会捕获无效,所以它不应该是MutableList<MutableList<BoardCellClass>>?类型,而是MutableList<MutableList<BoardCellClass>>,不是吗? 此外,MutableList<MutableList<BoardCellClass>>MutableList<MutableList<BoardCell>>兼容,因为它实现了该接口,对吗?

2 个答案:

答案 0 :(得分:1)

  

此外,MutableList<MutableList<BoardCellClass>>MutableList<MutableList<BoardCell>>兼容,因为它实现了该接口,对吗?

不,不是。这是variance的问题。正在寻找&#34; Kotlin方差&#34;会给你很多解释,但最简单的方法是查看为什么MutableList<BoardCellClass>不是MutableList<BoardCell>的子类型

val list: MutableList<BoardCellClass> = ...
val list1: MutableList<BoardCell> = list // illegal in actual Kotlin!
list1.add(object : BoardCell { ... }) // would add a BoardCell to a MutableList<BoardCellClass>

然后可以将相同的逻辑提升到一个级别,以查看MutableList<MutableList<BoardCellClass>>不是MutableList<MutableList<BoardCell>>的子类型。

  

显然,有一个if语句会捕获无效,所以它不应该是MutableList<MutableList<BoardCellClass>>?类型,而是MutableList<MutableList<BoardCellClass>>,不是吗?

Kotlin smart的投射方式并不完全(尽管差异在大多数情况下并不相关)。它仍属于MutableList<MutableList<BoardCellClass>>?类型,但如果在所需类型为MutableList<MutableList<BoardCellClass>>的地方使用,则会自动投放。MutableList<MutableList<BoardCell>>这里所需的类型为@implementation TableViewCell - (void)awakeFromNib { ... } - (void) layoutSubviews { [super layoutSubviews]; CGRect newFrame = UIEdgeInsetsInsetRect(self.layer.frame, UIEdgeInsetsMake(4, 0, 4, 0)); self.layer.frame = newFrame; } @end ,因此没有插入强制转换,并且可以为空的类型显示在错误消息中。

答案 1 :(得分:1)

  

MutableList&GT;兼容   MutableList&gt;,因为它实现了它   界面,对吧?

没有。在您的情况下,您可以使用out关键字

class AI(board: MutableList<MutableList<BoardCell>>, private var occupied: MutableList<out BoardCell>) {
    private var board: MutableList<MutableList<Cell>> = board.map { it.map { Cell(it.x, it.y, it.player, 0) } .toMutableList() } .toMutableList()
}
  

显然,有一个if语句可以捕获无效,所以它   不应该是

类型

您可以编写此代码,如果(不是其他)部分编译器以正确的方式理解您

if (request.board != null && request.occupied != null){
     val ai = AI(request.board, request.occupied)
} else {
    // respond with 403
}