说,我有一个带有执行方法的通用命令trait,它接受一个Input并返回一个Output。像
这样的东西trait Input;
trait Output;
trait Command[I <: Input, O <: Output] {
def execute(input: I): O;
}
然后,我将创建各种命令,类似于
class SampleInput extends Input
class SampleOutput extends Output
class SampleCommand extends Command[SampleInput, SampleOutput] {
def execute(input:SampleInput):SampleOutput = new SampleOutput()
}
这个问题是我可以使用SampleAInput
和SampleBOutput
创建一个命令,编译器会愉快地接受它。我如何强制执行,以便编译器因类型不匹配错误而失败?
不知何故,我需要在一个类型下对Input
和Output
进行分组并传递该类型以创建一个
命令。我该怎么做?
答案 0 :(得分:18)
trait InputOutput {
type Input
type Output
}
trait Command[IO <: InputOutput] {
def execute(input: IO#Input): IO#Output
}
以下是一些用法:
scala> trait SampleIO extends InputOutput {type Input = String; type Output = String}
defined trait SampleIO
scala> class SampleCommand extends Command[SampleIO] {def execute(input: String) = input}
defined class SampleCommand
scala> class SampleCommand extends Command[SampleIO] {def execute(input: String) = 1}
<console>:13: error: type mismatch;
found : Int(1)
required: SampleIO#Output
class SampleCommand extends Command[SampleIO] {def execute(input: String) = 1}
^
答案 1 :(得分:6)
由于你的约束是输入和输出的类型是相同的,我会尝试以下:
trait Input[T] trait Output[T] trait Command[T] { def execute[I <: Input[T], O <: Output[T]](i: I): O }
让我们尝试两种不同的类型。
class SampleInput extends Input[String] class SampleOutput extends Output[Int] scala> class SampleCommand extends Command[String] { | def execute(input: SampleInput): SampleOutput = new SampleOutput | } :10: error: class SampleCommand needs to be abstract, since method execute in trait Command of type [I <: Input[String],O <: Output[String]](i: I)O is not defined class SampleCommand extends Command[String] { ^
答案 2 :(得分:0)
我有点迟了,但是这个怎么样:
object inout {
trait ~>[I, O]
trait FooInput
trait FooOutput
trait BarOutput
//this specifies a valid input-output combination
implicit object fooInOut extends ~>[FooInput,FooOutput]
class Command[I, O](implicit val valid: I ~> O) {
def execute(input: I): O;
}
class FooCommand extends Command[FooInput, FooOutput]
//won't compile:
//class FubarCommand extends Command[FooInput, BarOutput]
}