我是Scala的新手,我正在尝试使用类型边界来避免代码重复在以下代码中(从不相关的东西中清除):
trait StandardStep1[-I1] {
def next_step(i:I1):StandardStep2
}
trait StandardStep2
trait UniqueStep1[-I1] extends StandardStep1[I1] {
def next_step(i:I1):UniqueStep2
}
trait UniqueStep2 extends StandardStep2
class DoubleStandardStep1[-IL,-IR](left:StandardStep1[IL], right:StandardStep1[IR]) extends StandardStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
val (i_left, i_right) = i
val new_left = left.next_step(i_left)
val new_right = right.next_step(i_right)
new DoubleStandardStep2(new_left, new_right)
}
}
class DoubleStandardStep2(left:StandardStep2, right:StandardStep2) extends StandardStep2
class DoubleUniqueStep1[-IL,-IR](left:UniqueStep1[IL], right:UniqueStep1[IR]) extends UniqueStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
val (i_left, i_right) = i
val new_left = left.next_step(i_left)
val new_right = right.next_step(i_right)
new DoubleUniqueStep2(new_left, new_right)
}
}
class DoubleUniqueStep2(left:UniqueStep2, right:UniqueStep2) extends UniqueStep2
说明:
StandardStep1
表示某个状态机中的一个步骤,并且具有next_step
操作,可为给定输入提供StandardStep2
。
UniqueStep1
是一种特殊类型的StandardStep1
,当UniqueStep2
被调用时会提供next_step
- 显然UniqueStep2
必须从{{1}继承为此。
现在我必须写一个 DoubleStep 包装器:StandardStep2
包装DoubleStandardStep1
s,并在调用StandardStep1
时返回DoubleStandardStep2
。
next_step
执行相同的操作,但会返回DoubleUniqueStep1
。
* DoubleStep * s'DoubleUniqueStep2
的实现有明显的代码重复:它们都将输入分成next_step
和i_left
并调用其包裹的步骤'{{1}以同样的方式。
我想知道如何通过创建将执行此部分代码的通用抽象 DoubleStep1 来消除此代码重复:
i_right
尝试编译此代码(scala 2.9.2)失败,并显示以下消息:
type mismatch; found : (this.StandardStep2, this.StandardStep2) required: (this.UniqueStep2, this.UniqueStep2) ((l,r) => new DoubleUniqueStep2(l,r)).tupled(DoubleStepHelper.next_step_args(left,right)(i)) ^
我认为发生这种情况是因为假定next_step
返回object DoubleStepHelper {
def next_step_args[IL,IR,SL <: StandardStep1[IL],SR <: StandardStep1[IR]](left:SL,right:SR)(i:(IL,IR)) = {
val (i_left, i_right) = i
val new_left = left.next_step(i_left)
val new_right = right.next_step(i_right)
(new_left, new_right)
}
}
class DoubleStandardStep1[-IL,-IR](left:StandardStep1[IL], right:StandardStep1[IR]) extends StandardStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
((l,r) => new DoubleStandardStep2(l,r)).tupled(DoubleStepHelper.next_step_args(left,right)(i))
}
}
class DoubleStandardStep2(left:StandardStep2, right:StandardStep2) extends StandardStep2
class DoubleUniqueStep1[-IL,-IR](left:UniqueStep1[IL], right:UniqueStep1[IR]) extends UniqueStep1[(IL,IR)] {
def next_step(i:(IL,IR)) = {
((l,r) => new DoubleUniqueStep2(l,r)).tupled(DoubleStepHelper.next_step_args(left,right)(i))
}
}
class DoubleUniqueStep2(left:UniqueStep2, right:UniqueStep2) extends UniqueStep2
值,当我们想要用 DoubleStepHelper.next_step_args
包裹它时,这是不好的。
你能想出解决这个问题的方法吗?如果(StandardStep2, StandardStep2)
DoubleUniqueStep2
和DoubleStepHelper
继承自(UniqueStep2, UniqueStep2)
,如何告诉编译器SL
的next_step_args可能会返回SR
?
一个不错的功能可能是能够将UniqueStep1
的结果类型定义为(SL.next_step,SR.next_step),这意味着它的返回类型是从next_step_args
和SL
中特定函数( next_step )的返回类型。
可以“查看”界限以任何方式解决它吗?
我可以使用 asInstanceOf 强制进行投射,但这看起来很难看。
由于
答案 0 :(得分:0)
我找到了一个很好的解决方案。我创建了AbstractStep1
和AbstractDoubleStep1
,其中给出了以下步骤的类型作为类型参数。
然后,我可以从下一步为StandardStep2
或UniqueStep2
的情况继承此类。
所以这是代码:
trait AbstractStep1[-I,+S2] {
def next_step(i:I):S2
}
trait StandardStep1[-I] extends AbstractStep1[I,StandardStep2]
trait StandardStep2
trait UniqueStep1[-I] extends AbstractStep1[I,UniqueStep2] with StandardStep1[I]
trait UniqueStep2 extends StandardStep2
abstract class AbstractDoubleStep1[-IL,-IR,-S2L <: StandardStep2,-S2R <: StandardStep2,+S2](left:AbstractStep1[IL,S2L],right:AbstractStep1[IR,S2R]) extends AbstractStep1[(IL,IR),S2] {
def wrapper(l:S2L,r:S2R):S2
def next_step(i:(IL,IR)):S2 = {
val (i_left, i_right) = i
val new_left = left.next_step(i_left)
val new_right = right.next_step(i_right)
wrapper(new_left, new_right)
}
}
class DoubleStandardStep1[-IL,-IR](left:StandardStep1[IL], right:StandardStep1[IR]) extends AbstractDoubleStep1[IL,IR,StandardStep2,StandardStep2,DoubleStandardStep2](left,right) {
def wrapper(l:StandardStep2,r:StandardStep2) = {
new DoubleStandardStep2(l,r)
}
}
class DoubleStandardStep2(left:StandardStep2, right:StandardStep2) extends StandardStep2
class DoubleUniqueStep1[-IL,-IR](left:UniqueStep1[IL], right:UniqueStep1[IR]) extends AbstractDoubleStep1[IL,IR,UniqueStep2,UniqueStep2,DoubleUniqueStep2](left,right) {
def wrapper(l:UniqueStep2,r:UniqueStep2) = {
new DoubleUniqueStep2(l,r)
}
}
class DoubleUniqueStep2(left:UniqueStep2, right:UniqueStep2) extends UniqueStep2
我认为也可以将AbstractDoubleStep1
转换为 triat 而不是抽象类,这将使它在mixin继承中更有用,但是这对我来说并不重要。