trait Body
    case class FancyBody(message: String)                    extends Body
    case class DefaultBody(message: String = "Unknown body") extends Body

    // TypeTags not used, but there if useful/needed
    def isaB[A, B <: A](x: A)(implicit ttA: TypeTag[A], ttB: TypeTag[B]): Boolean = {
      x.isInstanceOf[B]
    }

    println( isaB[Body, DefaultBody](DefaultBody()) )  // true--as expected
    println( isaB[Body, DefaultBody](FancyBody("Foo")) ) // also true --not expected

Я не уверен, почему передача FancyBody в isaB вернула true — это не DefaultBody. Как я могу их различать? Значение типа B всегда будет A, но A может быть или не быть B.

ПРИМЕЧАНИЕ. У меня не будет конкретных знаний об A или B, кроме этих отношений.

0
Greg 13 Ноя 2019 в 01:10

1 ответ

Я думаю, что это больше похоже на:

scala> def f[A, B <: A, C <: A](c: C)(implicit tB: TypeTag[B], tC: TypeTag[C]) = tC.tpe <:< tB.tpe
f: [A, B <: A, C <: A](c: C)(implicit tB: reflect.runtime.universe.TypeTag[B], implicit tC: reflect.runtime.universe.TypeTag[C])Boolean

scala> f[Body, DefaultBody, FancyBody](FancyBody("Foo"))
res0: Boolean = false

Также

scala> def isaB[A, B <: A](x: A)(implicit ttA: TypeTag[A], ttB: TypeTag[B]): Boolean = x.isInstanceOf[B]
                                                                                                     ^
       warning: abstract type B is unchecked since it is eliminated by erasure
isaB: [A, B <: A](x: A)(implicit ttA: reflect.runtime.universe.TypeTag[A], implicit ttB: reflect.runtime.universe.TypeTag[B])Boolean

Для обычной проверки во время выполнения сопоставление с образцом будет использовать ClassTag:

scala> def f[A: reflect.ClassTag](x: Any) = x match { case _: A => }
f: [A](x: Any)(implicit evidence$1: scala.reflect.ClassTag[A])Unit

scala> f[String]("")

scala> f[String](new Object)
scala.MatchError: java.lang.Object@2895e02b (of class java.lang.Object)
  at .f(<console>:1)
  ... 28 elided
1
som-snytt 13 Ноя 2019 в 02:16