使用scala中的duck typing避免代码重复
发布时间:2020-12-16 09:00:57 所属栏目:安全 来源:网络整理
导读:我目前正在使用 scala进行编码,我认为自己是新手. 我有3个不受我控制的课程,这意味着我无法改变它们. class Pclass A { def m(p: P): A = { println("A.m"); this }}class B { def m(p: P): B = { println("B.m"); this }} 这是一个简化的例子,实际代码更复
我目前正在使用
scala进行编码,我认为自己是新手.
我有3个不受我控制的课程,这意味着我无法改变它们. class P class A { def m(p: P): A = { println("A.m"); this } } class B { def m(p: P): B = { println("B.m"); this } } 这是一个简化的例子,实际代码更复杂,类A,B有许多其他类似的方法. 我需要为类A,B的实例调用方法m 明显的解决方案是: def fill(ab: AnyRef,p: P): Unit = { ab match { case a: A => a.m(p) case b: B => b.m(p) } } 但这涉及代码重复.我尝试用鸭子打字解决它,到目前为止,我对这个主题的最佳看法是: type WithM[T] = { def m(p: P): T } def fill[S,T <: WithM[S]](ab: T,p: P): S = ab.m(p) fill(new A,new P) 但我得到类型推断错误,如: Error:(18,5) inferred type arguments [Nothing,A] do not conform to method fill's type parameter bounds [S,T <: Test.WithM[S]] fill(new A,new P) ^ 这个问题可以用最少的魔法以优雅的方式解决吗? 解决方法
你有几个选择.一种是明确提供类型参数:
scala> fill[A,A](new A,new P) A.m res1: A = A@4beb8b21 如果m方法总是返回其定义的类型的值,则可以通过在填充中编码该事实来帮助进行类型推断: scala> def fill[T <: WithM[T]](o: T,p: P): T = o.m(p) fill: [T <: WithM[T]](o: T,p: P)T scala> fill(new A,new P) A.m res2: A = A@5f9940d4 您也可以跳过类型别名: scala> def fill[S](o: { def m(o: P): S },p: P): S = o.m(p) fill: [S](o: AnyRef{def m(o: P): S},p: P)S scala> fill(new A,new P) A.m res3: A = A@3388156e 我强烈建议使用类型类,但它有点语法开销但更清晰: trait HasM[T] { type Out def apply(t: T,p: P): Out } object HasM { type Aux[T,Out0] = HasM[T] { type Out = Out0 } implicit def AHasM: Aux[A,A] = new HasM[A] { type Out = A def apply(t: A,p: P): A = t.m(p) } implicit def BHasM: Aux[B,B] = new HasM[B] { type Out = B def apply(t: B,p: P): B = t.m(p) } } def fill[T](t: T,p: P)(implicit hm: HasM[T]): hm.Out = hm(t,p) 然后: scala> fill(new A,new P) A.m res4: A = A@74e92aa9 scala> fill(new B,new P) B.m res5: B = B@1ea35068 没有反思的访问,你正在使用一个广泛理解的习语. (编辑:李大同) 【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容! |