2010-12-20 30 views
6

说,我有一个通用的命令trait与一个执行方法,接受一个输入并返回一个输出。像如何使以下代码类型安全?

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() 
} 

的问题,这是我可以创建一个SampleAInputSampleBOutput,编译器将接受高兴地命令。我该如何执行,以便编译器因类型不匹配错误而失败?

不知何故,我需要将InputOutput组合在一个类型下,并通过该类型创建一个 命令。我怎么做?

回答

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} 
                       ^
+0

优秀!这正是我所期待的。谢谢IttayD。 – sanjib 2010-12-20 06:17:04

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] { 
      ^
+0

我喜欢它,无需耦合输入输出相同的特质。 – GClaramunt 2010-12-20 16:27:48

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] 
}