How to make the following code safe?

let's say I have a common feature of the command with the execute method, which accepts input and returns Output. Something like

trait Input; trait Output; trait Command[I <: Input, O <: Output] { def execute(input: I): O; } 

Then I'm going to create various teams, something like

 class SampleInput extends Input class SampleOutput extends Output class SampleCommand extends Command[SampleInput, SampleOutput] { def execute(input:SampleInput):SampleOutput = new SampleOutput() } 

The problem with this is that I can create a command with SampleAInput and SampleBOutput , and the compiler will accept this happily. How to enforce this so that the compiler crashes with a type mismatch error?

Somehow I need to group Input and Output under a type and pass this type to create a command. How to do it?

+6
types scala
source share
3 answers
 trait InputOutput { type Input type Output } trait Command[IO <: InputOutput] { def execute(input: IO#Input): IO#Output } 

Here are some uses:

 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} ^ 
+18
source share

Since your limitation is that the type of input and output will be the same, I would try the following:

  trait Input [T]
 trait Output [T]

 trait Command [T] {
   def execute [I <: Input [T], O <: Output [T]] (i: I): O  
 }

Try this with two different types.

  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] {
              ^
+6
source share

I'm a little late, but what about this:

 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] } 
0
source share

All Articles