Scalaで、継承関係の確認方法


Scalaの対話環境(REPL)で、クラス･トレイトの継承関係を確認する方法を探しています。

例えば、クラスA1とそれを継承したクラスA2があるとします。

[code]

    scala> class A1
    scala> class A2 extends A1
    
[/code]

このとき、以下のようにA2のインスタンスを作れば、A2はA1のサブクラスであることがわかります。

[code]

    scala> val a2 = new A2
    scala> a2.isInstanceOf[A1]
    res1: Boolean = true
    
[/code]

しかし、トレイトの場合はインスタンスが作れないので、このような方法では確認できません。

例えば、以下のようなときにトレイトB2とトレイトB1の継承関係を手軽に確認したいです。(いちいち抽象メンバを実装したりしたくない)

[code]

    scala> trait B1 {val i:Int}
    scala> trait B2 extends B1
    
[/code]

質問: 簡単にクラス･トレイトの継承関係を確認する方法はないでしょうか?




[Reflection API](http://docs.scala-lang.org/ja/overviews/reflection/typetags-
manifests.html) を使うとランタイム型を取得できます。

[code]

    $ scala
    Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> import scala.reflect.runtime.universe._
    import scala.reflect.runtime.universe._
    
    scala> trait A1 {}
    defined trait A1
    
    scala> class A2 extends A1 {}
    defined class A2
    
    scala> def isA1[A: TypeTag](a: A): Boolean = typeOf[A] <:< typeOf[A1]
    isA1: [A](a: A)(implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean
    
    scala> isA1(new A2)
    res0: Boolean = true
    
    scala> isA1(1)
    res1: Boolean = false
    
[/code]

**追記** :

Scala 2.9.x の場合は `Manifest` で似たことができますが、不正確な場合もあります。

[code]

    scala> import scala.reflect.Manifest
    import scala.reflect.Manifest
    
    scala> trait A1 {}
    defined trait A1
    
    scala> class A2 extends A1 {}
    defined class A2
    
    scala> def isApproxA1[A: Manifest](a: A) = manifest[A] <:< manifest[A1]
    isApproxA1: [A](a: A)(implicit evidence$1: scala.reflect.Manifest[A])Boolean
    
    scala> isApproxA1(new A2)
    res0: Boolean = true
    
    scala> isApproxA1(1)
    res1: Boolean = false
    
    scala> def isApproxSubType[A: Manifest, B: Manifest] = manifest[A] <:< manifest[B]
    isApproxSubType: [A, B](implicit evidence$1: scala.reflect.Manifest[A], implicit evidence$2: scala.reflect.Manifest[B])Boolean
    
    scala> trait A3 extends A1 {}
    defined trait A3
    
    scala> isApproxSubType[A3, A1]
    res3: Boolean = true
    
[/code]




[Reflection API](http://docs.scala-lang.org/ja/overviews/reflection/typetags-
manifests.html) を使うとランタイム型を取得できます。

[code]

    $ scala
    Welcome to Scala version 2.11.0 (Java HotSpot(TM) 64-Bit Server VM, Java 1.7.0_51).
    Type in expressions to have them evaluated.
    Type :help for more information.
    
    scala> import scala.reflect.runtime.universe._
    import scala.reflect.runtime.universe._
    
    scala> trait A1 {}
    defined trait A1
    
    scala> class A2 extends A1 {}
    defined class A2
    
    scala> def isA1[A: TypeTag](a: A): Boolean = typeOf[A] <:< typeOf[A1]
    isA1: [A](a: A)(implicit evidence$1: reflect.runtime.universe.TypeTag[A])Boolean
    
    scala> isA1(new A2)
    res0: Boolean = true
    
    scala> isA1(1)
    res1: Boolean = false
    
[/code]

**追記** :

Scala 2.9.x の場合は `Manifest` で似たことができますが、不正確な場合もあります。

[code]

    scala> import scala.reflect.Manifest
    import scala.reflect.Manifest
    
    scala> trait A1 {}
    defined trait A1
    
    scala> class A2 extends A1 {}
    defined class A2
    
    scala> def isApproxA1[A: Manifest](a: A) = manifest[A] <:< manifest[A1]
    isApproxA1: [A](a: A)(implicit evidence$1: scala.reflect.Manifest[A])Boolean
    
    scala> isApproxA1(new A2)
    res0: Boolean = true
    
    scala> isApproxA1(1)
    res1: Boolean = false
    
    scala> def isApproxSubType[A: Manifest, B: Manifest] = manifest[A] <:< manifest[B]
    isApproxSubType: [A, B](implicit evidence$1: scala.reflect.Manifest[A], implicit evidence$2: scala.reflect.Manifest[B])Boolean
    
    scala> trait A3 extends A1 {}
    defined trait A3
    
    scala> isApproxSubType[A3, A1]
    res3: Boolean = true
    
[/code]

