2016-02-27 86 views
2

說我們有這些嵌套類和A一個實例:去除類型檢查路徑依賴在斯卡拉

class A { 
    case object B 
    case class C(c: Int) 
} 
val a1 = new A() 

現在我可以檢查a1.Ba1.B.type實例,但我怎麼能檢查類型a1.B的任意一個A#B.type的實例,因爲編譯器不會接受該語法。

a1.B.isInstanceOf[a1.B.type] 
res: Boolean = true 

a1.B.isInstanceOf[A#B.type] 
<console>:1: error: ']' expected but '.' found. 
a1.B.isInstanceOf[A#B.type] 
        ^

對於案例類似乎沒有問題的工作:

a1.C(0).isInstanceOf[a1.C] 
res: Boolean = true 

a1.C(0).isInstanceOf[A#C] 
res: Boolean = true 

後續問題:當我有

val a1 = new A() 
val a2 = new A() 

有,做一個平等的檢查沒有功能考慮路徑依賴性?例如。在比較a1.Ba2.B時應該返回true。例如:

a1.B =#= a2.B 
true 

a1.C(0) =#= a2.C(0) 
true 

a1.C(0) =#= a2.C(1) 
false 

編輯:爲了澄清:只是引入一個共同的特點爲B是不夠的,因爲我想打賭能情況來區分對象:

class A { 
    trait BB 
    case object B1 extends BB 
    case object B2 extends BB 
} 
val a1 = new A 
val a2 = new A 

a1.B1 =#= a2.B1 // should be true 
a1.B2 =#= a2.B2 // should be true 
a1.B1 =#= a1.B2 // should be false 
a1.B1 =#= a2.B2 // should be false 

現在,.hashCode (或.##)方法似乎解決了這個問題:

a1.B1.## == a2.B1.## // true 
a1.B1.## == a2.B2.## // false 

但也許它ther e是一個更優雅的解決方案(我也希望能夠在模式匹配中使用a1.B1)。

+0

您是否在尋找運行時(即後擦除)測試? –

+0

我通過將'case object'移出外部類來解決我的問題,所以它現在更像是一個普遍問題。我想對於運行時值相等檢查,如果沒有更好的方法,可以通過比較'hashCode'來解決。 – Debilski

+0

你想檢查是否應該或'a1.C(0)== a2.C(0)'?如果它應該使用'final case class' –

回答

4

只需使用完整的形式表達存在的類型。

這裏您例如:

class A { 
    case object B1 
    case object B2 
    case class C(c: Int) 
} 
val a1 = new A() 

我已經添加了另一起案件中的對象,以證明他們可以區分,所以我還沒有寫AnyRef

type AB1 = a.B1.type forSome {val a : A} 
type AB2 = a.B2.type forSome {val a : A} 

scala> a1.B1.isInstanceOf[AB1] 
res0: Boolean = true 

scala> a1.B1.isInstanceOf[AB2] 
res1: Boolean = false 

我有一個不起眼的等價爲了方便,引入了類型別名AB1AB2。但如果有需要,可以將這些類型內聯到isInstanceOf

1

我認爲a1.B.isInstanceOf[A#B.type]在語法上是錯誤的。沒有.type

如何使用內部特質

class A{ 
    trait BTrait 
    object B extends BTrait 
    } 

    val a1 = new A 
    a1.B.isInstanceOf[A#BTrait] // this is true 
如果你希望你的內心實例是外實例的平等獨立

a1.C(0) == a2.C(0) 

是TURE如果聲明C as

final case class C() 

th是object小號

+0

我的問題是,我有'對象B1擴展BTrait;對象B2擴展BTrait; ...'。只要檢查「A#BTrait」是不夠的。 – Debilski

+0

我不明白你的觀點。你可以編輯你的問題。 –

+1

'對象B1擴展BTrait;對象B2擴展BTrait;'是你的選擇。使用'對象B1擴展BTrait1;對象B2擴展了BTrait2;'如果你需要普通的東西,則添加一個'CommonStuffTrait'給兩者。 'BTrait'只能用於類型檢查。 –

0

不工作,我不知道這是一個純粹的語法的事情,但以下似乎解決它:

class A { 
    case object B 
    type BType = B.type 
    case class C(c: Int) 
} 
val a1 = new A() 
val a2 = new A() 

a1.B.isInstanceOf[a1.B.type] 
res: Boolean = true 

a1.B.isInstanceOf[A#BType] 
res: Boolean = true 

,然後我可以殺(2。11)編譯器

a1.B match { 
    case _: A#BType => println("ABC") 
} 

> error: scala.MatchError: (?_1.type#B.type,a1.B.type) (of class scala.Tuple2) 

在瘋瘋癲癲它的工作原理,但並有趣的是a1.B.typea1.BType是不同的:

List(a1, a2) foreach { a => 
    a.B match { 
    case _: a1.B.type => println("Matches a1") 
    case _: a2.B.type => println("Matches a2") 
    case _: A#BType => println("Matches a1 and a2") 
    case _: a1.BType => println("Matches a1 and a2") 
    case _: a2.BType => println("Matches a1 and a2") 
    case x => println(x) 
    } 
}