Ответ 1
Вы можете делать такие вещи безопасным типом, используя классы типов. Например, предположим, что у вас есть класс этого типа:
trait Default[A] { def apply(): A }
И следующая иерархия типов:
trait Stage
case class FooStage(foo: String) extends Stage
case class BarStage(bar: Int) extends Stage
И в некоторых случаях:
trait LowPriorityStageInstances {
implicit object barStageDefault extends Default[BarStage] {
def apply() = BarStage(13)
}
}
object Stage extends LowPriorityStageInstances {
implicit object stageDefault extends Default[Stage] {
def apply() = FooStage("foo")
}
}
Затем вы можете написать свой метод следующим образом:
def getStage[T <: Stage: Default](key: String): T =
implicitly[Default[T]].apply()
И он работает следующим образом:
scala> getStage("")
res0: Stage = FooStage(foo)
scala> getStage[BarStage]("")
res1: BarStage = BarStage(13)
Что я думаю, более или менее то, что вы хотите.