21

Is it possible (via macros, some form of Shapeless automagic or otherwise) to obtain a list of the subclasses of a sealed trait:

  • At compile time?
  • At runtime?
NietzscheanAI
  • 966
  • 6
  • 16
  • 1
    Yes. We are using https://github.com/julienrf/play-json-variants, which does that you can use it as a reference – mavarazy Dec 30 '15 at 19:00
  • @mavarazy Thanks for this. The code is quite dependent on the Play framework and its not readily apparent (to me anyway) how to factor out the minimum required functionality: would you care to post a self-contained variant of the `baseAndVariants' etc functionality as an answer? – NietzscheanAI Dec 31 '15 at 09:13

1 Answers1

33

You don't need any 3rd party library to do this:

sealed trait MyTrait

case object SubClass1 extends MyTrait
case object SubClass2 extends MyTrait

import scala.reflect.runtime.{universe => ru}

val tpe = ru.typeOf[MyTrait]
val clazz = tpe.typeSymbol.asClass
// if you want to ensure the type is a sealed trait, 
// then you can use clazz.isSealed and clazz.isTrait
clazz.knownDirectSubclasses.foreach(println)

Output:

object SubClass1

object SubClass2

Community
  • 1
  • 1
Max
  • 2,065
  • 24
  • 20
  • Thanks - this works at object scope, but doesn't appear to work inside a function: under Scala 2.11.7, I get: * No TypeTag available for this.MyTrait * not enough arguments for method typeOf: (implicit ttag: reflect.runtime.universe.TypeTag[this.MyTrait])reflect.runtime.universe.Type. Unspecified value parameter ttag. – NietzscheanAI Dec 31 '15 at 19:15
  • 1
    How do you mean by `inside a function`? Can you edit the question with your code? – Max Dec 31 '15 at 20:12
  • 1
    now sorted: in my particular use case (calling the above functionality inside a generic function) merely requires a TypeTag so that ru.typeOf can be invoked on the generic type. – NietzscheanAI Jan 01 '16 at 09:57