Как сделать следующий тип кода безопасным? - PullRequest
6 голосов
/ 20 декабря 2010

скажем, у меня есть общая черта команды с методом execute, который принимает входные данные и возвращает выходные данные. Что-то вроде

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 по типу и передать этот тип для создания команда. Как мне это сделать?

Ответы [ 3 ]

18 голосов
/ 20 декабря 2010
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}
                                                                                 ^
6 голосов
/ 20 декабря 2010

Поскольку вы ограничены тем, что тип ввода и вывода одинаков, я бы попробовал следующее:

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 голосов
/ 20 декабря 2010

Я немного опоздал, но как насчет этого:

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]
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...