2010-12-20 51 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] 
}