Алмазная проба Scala, найти имя класса из экземпляра класса D

У меня есть четыре черты A, B, C и D в типичной иерархии задач с бриллиантами. Я реализовал метод calculate в трейте A, который проверяет экземпляр callerObject, выполняет некоторые вычисления и возвращает объект типа трейта A. Метод calculate успешно может проверить тип экземпляра callerObject, когда callerObject принадлежит типу B или C, но не работает для объекта типа D, и я получаю следующее исключение приведения класса:

java.lang.ClassCastException: packageName.B$$anon$1 cannot be cast to packageName.D

Не могли бы вы предложить путь вперед, как я могу проверить тип объекта из черты D в методе черты A.

PS: я новичок в Scala.


person user1809095    schedule 31.01.2016    source источник
comment
def calculate(other: A) : A = { this match { case _: B =› // Вызов некоторой функции и возврат obj типа B case _: C = › // Вызов некоторой функции и возврат obj типа C case _: D =› //Вызов какой-то функции и возврат объекта типа D obj } }   -  person user1809095    schedule 31.01.2016
comment
Нет, я не могу это читать. Добавьте его к исходному вопросу, правильно отформатируйте и покажите, где вы получаете ошибку. Добавьте также определения классов. См. руководство здесь: stackoverflow.com/help/mcve   -  person Dima    schedule 31.01.2016
comment
Конечно, я скоро опубликую чистый код.   -  person user1809095    schedule 31.01.2016


Ответы (1)


При сопоставлении с образцом порядок операторов case имеет значение. Убедитесь, что самый конкретный класс всегда совпадает вверху. Например, если B extends A и C extends B, это означает, что объекты C всегда будут соответствовать всему, что ищет B или A и т. д.

Вот игрушечный пример, который может лучше объяснить решение:

sealed trait A {
   def calculate(i: A) = i match {
      case _:D => "d" // Make sure the D is checked first!
      case _:B => "b"
      case _:C => "c"
      // If you want to match for A make sure it is added last
   }
}
trait B extends A
trait C extends A
trait D extends B with C

Вот пример в REPL:

val b = new B{}
val c = new C{}
val d = new D{}

b.calculate(b)
res> "b"
b.calculate(c)
res> "c"
b.calculate(d)
res> "d"
person marios    schedule 31.01.2016
comment
Именно изменение порядка, как было предложено выше, сработало для меня, большое спасибо. - person user1809095; 01.02.2016