Scala 3如何通过MirroredElemTypes实现List[String]转样例类实例
Scala 3 通用String列表转样例类实现方案
你可以通过定义转换类型类+编译期自动获取字段类型实例的方式实现完全通用的转换,不需要硬编码任何类型判断逻辑,完整实现如下:
首先定义通用字符串转换的类型类,统一不同类型的转换逻辑:
// 字符串转目标类型的类型类 trait FromString[T]: def apply(s: String): T object FromString: // 内置常用类型的转换实例,需要支持其他类型直接在这里加即可 given FromString[String] = identity(_) given FromString[Int] = _.toInt given FromString[Double] = _.toDouble
然后实现通用转换方法,通过MirroredElemTypes自动获取样例类所有字段对应的转换实例:
import scala.deriving.Mirror import scala.compiletime.summonAll def listStringToClass[A](stringValues: List[String])(using m: Mirror.ProductOf[A]): A = // 编译期自动获取样例类所有字段对应的FromString转换实例 val converters = summonAll[Tuple.Map[m.MirroredElemTypes, FromString]] .toList.asInstanceOf[List[FromString[Any]]] // 运行时校验输入长度和样例类字段数匹配,避免非法输入 require(stringValues.length == converters.length, s"输入列表长度(${stringValues.length})和样例类字段数(${converters.length})不匹配") // 逐个转换字符串为对应字段类型 val convertedValues = stringValues.zip(converters).map((str, conv) => conv(str)) // 构造Tuple后直接生成样例类实例 m.fromProduct(Tuple.fromArray(convertedValues.toArray))
测试用例:
case class Foo(aString: String, aDouble: Double, aInt: Int) @main def test() = val result = listStringToClass[Foo](List("bob", "2.2", "1")) println(result) // 输出:Foo(bob,2.2,1)
实现说明
- 不需要硬编码任何类型判断,所有转换逻辑通过类型类实例匹配,编译期自动完成对应关系映射
- 新增支持的字段类型只需要在
FromString伴生对象中加对应的given实例即可,无需修改核心转换代码 - 如果样例类字段存在没有对应
FromString实例的类型,编译期就会报错,比运行时类型判断更安全
内容的提问来源于stack exchange,提问作者gekomad
相关产品推荐
相关产品推荐

