我正在使用 scala 2.11。我對 scala 泛型型別和模式匹配有疑問。
在課堂MyImpl.example()上,編譯器不高興地說type mismatch, Required: _$1, Found: X[_ <: A]
trait A
class B extends A
class C extends A
trait Foo[T <: A] {
def foo(arg: T): Unit
}
class Bar extends Foo[B] {
override def foo(arg: B): Unit = print("Bar")
}
class Car extends Foo[C] {
override def foo(arg: C): Unit = print("Car")
}
class MyImpl {
def getA(): A = {
new B()
}
def example(): Unit = {
getFoo("1").foo(getA())
}
def getFoo(something: String): Foo[_ <: A] = {
//return either
something match {
case "1" => new Bar()
case "2" => new Car()
}
}
}
object Test {
def main(args: Array[String]) = {
new MyImpl().example()
}
}
注意: getFoo("1") 在我的真實案例中更加動態,這里只是一個例子。
我有點理解這一點,編譯器無法預測呼叫該方法的 2 個實作中的哪一對。
如果我將實作更改MyImpl.example()為
def example(): Unit = {
(getFoo("1"), getA()) match {
case (i: Bar, j: B) => i.foo(j)
case (i: Car, j: C) => i.foo(j)
}
}
我對此并不滿意,因為我只是在重復i.foo(j)
任何 scala 功能樣式都可以撰寫更簡潔的代碼?
uj5u.com熱心網友回復:
基本上你想要類似的東西
(getFoo("1"), getA()) match {
case (i: Foo[t], j: t) => i.foo(j) // doesn't compile, not found: type t
}
或者
(getFoo("1"), getA()) match {
case (i: Foo[t], j: Id[t]) => i.foo(j) // doesn't compile, t is already defined as type t
}
type Id[T] = T
您可以洗掉代碼重復
def example(): Unit = { // (*)
(getFoo("1"), getA()) match {
case (i: Bar, j: B) => i.foo(j)
case (i: Car, j: C) => i.foo(j)
}
}
(或修復編譯getFoo("1").foo(getA()))
使用嵌套模式匹配
getFoo("1") match {
case i => getA() match {
case j: i._T => i.foo(j)
}
}
如果您添加型別成員_T
trait Foo[T <: A] {
type _T = T
def foo(arg: T): Unit
}
對于getFoo("1")和getA產生new B這個列印Bar,反之亦然,對于getFoo("2")和new C這個列印Car,對于其他組合,這個拋出ClassCastException類似于(*)。
請注意,這不能僅重寫為變數宣告和單一模式匹配
val i = getFoo("1")
getA() match {
case j: i._T => i.foo(j)
}
//type mismatch;
// found : j.type (with underlying type i._T)
// required: _$1
因為對于嵌套模式匹配,型別被正確推斷(i: Foo[t], j: t)但val i型別是存在的(i: Foo[_]也就是i: Foo[_$1]在skolemization之后j: _$1)。
轉載請註明出處,本文鏈接:https://www.uj5u.com/ruanti/515730.html
