簡體   English   中英

即使在使用 isInstanceOf 檢查類型后 Scala 類型不匹配錯誤

[英]Scala type mismatch error even after checking type with isInstanceOf

我有一個函數unlist將任何類型的列表作為第一個參數:

def unlist(xs: List[Any], ys: List[Any]): List[Any] = ...

我在外部列表的第一個元素上調用這個函數,它可能是也可能不是列表。 因此,我首先需要檢查這個 head 元素本身是否是一個列表,在這種情況下我可以調用我的unlist函數。 我用InsintanceOf方法來做,就像這樣:

...
if (xs.head.isInstanceOf[List[Any]]) unlist(xs.head, ys)

但是,由於 xs.head 上的類型不匹配,這不會編譯:

Error: type mismatch;
found   : Any
required: List[Any]

我究竟做錯了什么?


PS :由於你們中的許多人建議避免使用Any類型,我必須指出這是編碼練習的一部分,旨在使函數盡可能通用

為了說明 Mateusz 的評論

isInstanceOf沒有被記住

這意味着我們必須像這樣跟進asInstanceOf

if (list.head.isInstanceOf[List[_]]) unlist(list.head.asInstanceOf[List[_]])

模式匹配,如 Tim 所演示的,隱式執行isInstanceOf/asInstanceOf組合。 還可以考慮相關答案

如果您無法重構Any ,這是最弱的類型,也許嘗試盡早恢復盡可能多的類型信息,也許像這樣

val lists: List[List[_]] = list.collect { case xs: List[_] => xs }
val ints: List[Int] = list.collect { case i: Int => i }
val strings: List[String] = list.collect { case s: String => s }

請注意,由於類型擦除,我們不能輕易做得比List[List[_]]好得多,例如,以下斷言通過

val list: List[Any] = List(List("woo", "hoo"), 42, "kerfuffle")
assert(list.head.isInstanceOf[List[Double]])

在最后一種情況下,編譯器警告會告訴您type argument Double in type List[Double] (the underlying of List[Double]) is unchecked since it is eliminated by erasure 忽略此類警告通常不是一個好主意。

正如評論中提到的,像這樣使用Any是一些糟糕設計選擇的標志。 但是對於您遇到的特定問題,您可以將if更改為這樣的match

def unlist(xs: List[Any], ys: List[Any]): List[Any] = ???

val xs: List[Any] = ???

xs.head match {
  case l: List[Any] => unlist(l, ???)
  case _ =>
}

match檢查頭部值是否為List[Any]然后將該值分配給類型為List[Any]的變量l ,因此可以在unlist調用中使用。

注意:這僅適用於您正在測試List[Any] 您無法測試特定類型的列表(例如List[Int] ),因為稱為類型擦除的進程會刪除運行時信息,而此信息將需要此操作。 當編譯器因此無法實現match時,它會警告您。

這個問題的真正解決方案是修復設計以使用特定類型而不是Any

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM