Scala如何从match case推断方法返回类型以简化处理器定义
方案可行性说明
你的思路完全可行,Scala编译器可以通过模式匹配的类型细化能力自动识别返回类型,以下两种常用方案可以大幅简化处理器定义,消除重复代码。
方案1:绑定输入输出类型,合并多处理器为单个泛型方法(保留match写法)
首先修改基础trait定义,给输入类型绑定对应的输出类型,建立两者的映射关系:
trait InputBaseType { // 绑定当前输入类型对应的输出类型上限 type OutputType <: OutputBaseType } trait OutputBaseType {} // 实现类直接指定自身对应的输出类型即可 class InputTypeA extends InputBaseType { override type OutputType = Output class Output extends OutputBaseType {} } class InputTypeB extends InputBaseType { override type OutputType = Output class Output extends OutputBaseType {} } class InputTypeC extends InputBaseType { override type OutputType = Output class Output extends OutputBaseType {} }
无需再定义N个独立的handleTypeX方法,仅需一个泛型处理方法,返回类型会被编译器自动推断:
// 处理器返回类型自动对应输入类型绑定的OutputType private def handle[T <: InputBaseType](input: T): T#OutputType = input match { case a: InputTypeA => /* 直接写原handleTypeA的处理逻辑 */ case b: InputTypeB => /* 直接写原handleTypeB的处理逻辑 */ case c: InputTypeC => /* 直接写原handleTypeC的处理逻辑 */ }
原来的match调用处直接替换为handle(input)即可,无需再写重复分支。
方案2:用类型类完全消除match语句,无额外分支判断
如果需要彻底消除match分支、后续新增输入类型无需修改已有代码,可以用类型类实现:
首先定义处理逻辑的类型类模板:
trait InputHandler[T <: InputBaseType] { def handle(input: T): T#OutputType }
给每个输入类型提供对应的类型类实例,放在伴生对象中编译器会自动搜索:
object InputHandler { given InputHandler[InputTypeA] with { override def handle(input: InputTypeA): InputTypeA#OutputType = /* 处理逻辑 */ } given InputHandler[InputTypeB] with { override def handle(input: InputTypeB): InputTypeB#OutputType = /* 处理逻辑 */ } given InputHandler[InputTypeC] with { override def handle(input: InputTypeC): InputTypeC#OutputType = /* 处理逻辑 */ } }
调用时无需写任何match,自动匹配对应处理逻辑:
import InputHandler.given def handle[T <: InputBaseType : InputHandler](input: T): T#OutputType = summon[InputHandler[T]].handle(input)
两种方案的返回类型都可以完全由编译器自动推断,不需要显式声明,也不存在类型安全问题。
内容的提问来源于stack exchange,提问作者Kyuubi
相关产品推荐
相关产品推荐

