How can we extract the name/type of “P” preferrably in compile-time?
Given the following traits:
trait Plugin
trait NetworkPlugin extends Plugin
trait StoragePlugin extends Plugin
and the event class:
case class Event[P <: Plugin](
// How do we know the name give the plugin type (P)?
val eventType: Class[P] = ???
val eventName: String = ???
)
It sounds like you’re skirting dangerously close to “you can’t do that, because of erasure” (which is a big and important topic when you’re trying to do things like this to generics). Suffice it to say, there are a lot of things you can’t just casually do with type parameters.
That said, you can get at least some information about P by using the ClassTag type class, which creates a synthetic implicit parameter with information about the specified type. It’s imprecise (which can matter when trying to do more-sophisticated things), but if all you need is the Class object and name of an ordinary trait, it will suffice. I use it moderately often to do things like this.
import scala.reflect.ClassTag
trait Plugin
trait NetworkPlugin extends Plugin
trait StoragePlugin extends Plugin
case class Event[P <: Plugin : ClassTag]() {
// How do we know the name give the plugin type (P)?
val eventType: Class[?] = summon[ClassTag[P]].runtimeClass
val eventName: String = eventType.getSimpleName()
}
val networkEvent = Event[NetworkPlugin]()
val storageEvent = Event[StoragePlugin]()
println(networkEvent.eventName)
println(storageEvent.eventName)
You can create an array whose element types are designated by the type variable:
import scala.reflect.ClassTag
object TypeErasureTag:
// No ClassTag available for T
// def createArray[T](length: Int, element: T) = new Array[T](length)
def createArray[T: ClassTag](length: Int, element: T): Array[T] =
val arr = new Array[T](length)
if length > 0 then arr(0) = element
arr
@main def runTypeErasureTag():Unit =
println(createArray(1, "howdy").toList.toString)