簡體   English   中英

如何為asInstanceOf指定鏈接類型

[英]How to specify linked types for asInstanceOf

標題不太具描述性,但我不知道如何正確調用所使用的模式。 我希望所有人都能以身作則。

trait OneKnot[K <: Knot[K]] { this : K#One =>
  type OK = K // for example only. To show that it is actually defined
  def use(second : OK#Two)
}
trait TwoKnot[K <: Knot[K]] { this : K#Two => }

trait Knot[K <: Knot[K]] {
  type One <: OneKnot[K]
  type Two <: TwoKnot[K]
}

trait KnotExample extends Knot[KnotExample] {
  override type One = OneExample
  override type Two = TwoExample
}

trait OneExample extends OneKnot[KnotExample]
trait TwoExample extends TwoKnot[KnotExample]

object Test {
  def testByName( one : OneExample, two : TwoExample ) = one.use(two)
  def testByKnot[K <: Knot[K]]( one : K#One, two : K#Two ) = one.use(two)
  def testByCast(knot : Knot[_], one : OneKnot[_], two : TwoKnot[_]) = one.asInstanceOf[knot.One].use(two.asInstanceOf[knot.Two])
  def testByInnerCast(one : OneKnot[_], two : TwoKnot[_]) = one.use( two.asInstanceOf[one.OK#Two] )
}

通常可以相互識別類型OneExampleTwoExample testByKnot方法顯示它。 我還可以通過Knot調用帶有靜態參數化的use方法。 類型將兼容,如testByKnot方法所示。

但是我需要丟棄類型信息以將數據存儲在集合中。 例如Map[Knot[_], OneKnot[_]] 所以我需要使用asInstanceOf從集合中提取數據后還原類型。 但是我無法正確指定所需的轉換類型。

在最后兩種測試方法中,我得到兩個相應的錯誤:

NotSameType.scala:25: error: type mismatch;
 found   : knot.Two
 required: _$1#Two
  def testByCast(knot : Knot[_], one : OneKnot[_], two : TwoKnot[_]) = one.asInstanceOf[knot.One].use(two.asInstanceOf[knot.Two])
                                                                                                                      ^
NotSameType.scala:26: error: type Two is not a member of one.OK
  def testByInnerCast(one : OneKnot[_], two : TwoKnot[_]) = one.use( two.asInstanceOf[one.OK#Two] )

如何正確地進行投射?

如何使用類型K <: Knot[K]將兩種類型的結粘合/澆鑄在一起?

object Test {
  def testByName(one: OneExample, two: TwoExample) = one.use(two)
  def testByKnot[K <: Knot[K]](one: K#One, two: K#Two) = one.use(two)
  def testByCast[K <: Knot[K]](one: OneKnot[_], two: TwoKnot[_]) =
    one.asInstanceOf[K#One].use(two.asInstanceOf[K#Two])
  def testByInnerCast[K <: Knot[K]](one: OneKnot[_], two: TwoKnot[_]) =
    one.asInstanceOf[K#One].use(two.asInstanceOf[K#One#OK#Two])
}

然后,您可以直接調用其中一種強制轉換方法。

val one    = new OneExample { def use(second: TwoExample) = ??? }
val two    = new TwoExample {}
val result = testByCast(one, two)

答案總結了安迪建議的方法

您可以使用類型參數化,但不要指定所需的標簽。 查看示例:

def testByDiscard[K <: Knot[K]]( one : OneKnot[_], two : TwoKnot[_] ) =
  one.asInstanceOf[K#One].use(two.asInstanceOf[K#Two])

神秘之處在於,編譯器設法將有意義的內容替換為類型參數。 類型參數可能永遠不會被指定,但是這種構造仍然有效。 無論如何,java擺脫了所有類型參數,因此不會丟失任何關鍵信息。

我很好奇編譯器使用什么魔術類型。 並添加隱式類型標記以獲取它。 只是簡單Nothing不是復雜的類型擦除類型。 靜態類型檢查器確實不再抱怨進一步的用法:

val exo : OneExample = new OneExample
val ext : TwoExample = new TwoExample
Test.testByDiscard[Nothing](exo, ext)

但是嘗試直接轉換為Nothing#OneNothing#Two時,按預期方式失敗。 當嘗試調用與廢棄情況相同但沒有asInstanceOf調用的testByKnot[Nothing] ,它也會失敗。 scala類型管理器的工作方式非常有趣,但是值得單獨提出一個問題。

這個問題已經由安迪(Andy)提供並在上面由我詳細介紹了。 它只是工作。

暫無
暫無

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

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