2016-02-27 1 views
2

Скажет, у нас есть эти вложенные классы и конкретизация A:Удаления путь-зависимость от проверки типа в Scala

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

Теперь я могу проверить, что a1.B является экземпляром a1.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.B и a2.B. Например:

a1.B =#= a2.B 
true 

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

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

Edit: Для уточнения: Просто введение общей чертой для 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

Я решил свою проблему, переместив «случайный объект» из внешнего класса, поэтому теперь это скорее общий вопрос. Я полагаю, что для проверки равенства значений времени выполнения можно обойтись, сравнивая «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 

Я введенные псевдонимы типов AB1 и AB2 для удобства. Но эти типы могут быть включены в 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) 

является ры, если вы объявите C как

final case class C() 

th это не работает для object s

+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.type и a1.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) 
    } 
}