Scala如何实现接收泛型匿名函数批量处理Farm中所有Legged实例
方案1:最小改动版本(无需修改原有定义)
你不需要自定义LeggedFunc特质,直接接收Legged => Legged类型的函数即可。由于所有Legged实现类的updateLegs方法都会返回自身类型的实例,这里的类型转换是完全安全的,不会出现运行时错误:
case class Farm(chicken: Chicken, dog: Dog) { def mapAll(leggedFunc: Legged => Legged): Farm = { copy( chicken = leggedFunc(chicken).asInstanceOf[Chicken], dog = leggedFunc(dog).asInstanceOf[Dog] ) } }
测试效果完全符合预期:
val farm = Farm(Chicken(1500), Dog("Max")) val newFarm = farm.mapAll(mutate) println(newFarm.chicken.legs) // 输出3 println(newFarm.dog.legs) // 输出5
方案2:全类型安全版本(无强制转换)
如果你想彻底避免asInstanceOf,可以用F-有界多态优化Legged特质的定义,让updateLegs直接返回具体子类的类型:
- 改造
Legged特质:
trait Legged[T <: Legged[T]] { self: T => val legs: Int def updateLegs(legs: Int): T }
- 调整实现类的声明:
case class Chicken(feathers: Int, legs: Int = 2) extends Legged[Chicken] { override def updateLegs(legs: Int): Chicken = copy(legs = legs) } case class Dog(name: String, legs: Int = 4) extends Legged[Dog] { override def updateLegs(legs: Int): Dog = copy(legs = legs) }
- 把
mutate改为泛型方法:
def mutate[T <: Legged[T]](legged: T): T = legged.updateLegs(legged.legs + 1)
- 实现
Farm的mapAll方法,全程无强制转换:
// Scala 3版本支持多态函数的写法 case class Farm(chicken: Chicken, dog: Dog) { def mapAll(f: [T <: Legged[T]] => T => T): Farm = { copy( chicken = f(chicken), dog = f(dog) ) } }
Scala 2版本不支持多态函数语法的话,直接沿用方案1的实现即可,运行风险为0。这个方案完全在编译期保证类型安全,没有任何运行时风险,也不需要模式匹配。
内容的提问来源于stack exchange,提问作者Random42
相关产品推荐
相关产品推荐

