Scala: Несоответствие типов ошибок - PullRequest
2 голосов
/ 23 апреля 2011

Я борюсь с системой типов.В строке

handler.addJob(job1)

появляется "ошибка: несоответствие типов"1008 * с типом, который расширяет Event, но я не могу понять, как это сделать.

Также строка

var jobs = List[Job[Event]]()

, вероятно, должна получить работу с подтипом Event, но, опять же, я не знаю, как это сделать.Любая помощь приветствуется.

-Eric

class EventHandler {
  var jobs = List[Job[Event]]()

  def receive(event: Event) {
    jobs.foreach {
      _.processEvent(event)
    }
  }

  def addJob(job: Job[Event]) {
    jobs = job :: jobs
  }
}

class Job[T <: Event] {
  var steps = List[(T => Unit)]()

  def addStep(step: (T => Unit)) {
    steps = step :: steps
  }

  def processEvent(event: T): Boolean = {
    steps.foreach(_.apply(event))
    return true
  }
}

class AppTest {
  def testApp {
    val handler = new EventHandler()
    val job1 = new Job[MessageEvent]
    job1.addStep {
      println(_)
    }
    handler.addJob(job1)
    handler.receive(new MessageEvent(new Message()))
  }
}

Ответы [ 3 ]

0 голосов
/ 23 апреля 2011

Изменение addJobs:

def addJob[T <: Event](job: Job[T]) {
  jobs = job :: jobs
}

Но jobs не будет работать с этим, поскольку Job[MessageEvent] не является Job[Event]. Единственный способ получить это - сделать Job ко-вариант, но, к сожалению, вы не можете сделать Job ко-вариант как есть.

Почему бы вам полностью не удалить параметризацию Job и не использовать Event для внутреннего использования? Затем вы можете использовать T <: Event (как указано выше в addJob) с addStep и processEvent, если необходимо.

0 голосов
/ 23 апреля 2011

Исходя из вашего примера, создается впечатление, что вы будете строить экземпляры Job и EventHandler статически.В этом случае вам вообще не нужны эти классы!

Начиная с Job.Он выполняет две роли:

  1. поддерживает список T => Unit функций
  2. выполняет эти функции

(также стоит отметить, что :: предваряется, поэтому шаги будут выполняться в порядке, обратном тому, в котором они были добавлены)

Создание и ведение этого списка функций во время выполнения (в изменяемом списке) можно полностью избежать, если вы ужезнать, что они будут, когда вещь компилируется.Это наиболее естественно сделать с помощью агрегатной функции:

val job = (m: MessageEvent) => {
  log.debug(m)
  println(m)
  somethingElse(m)
}

Вместо удержания List[Job[Event]] это означает, что EventHandler теперь содержит List[(T => Unit)] (как ранее Job).Так что промыть и повторить ...

0 голосов
/ 23 апреля 2011

Упомянутые вами проблемы легко решить:

class EventHandler {
  var jobs = List[Job[_]]()

  def receive(event: Event) {
    jobs.foreach {
      _.processEvent(event)
    }
  }

  def addJob(job: Job[_]) {
    jobs = job :: jobs
  }
}

Но это показывает еще одну проблему с методом receive: вам нужно каждый job для обработки любого Event. Это можно исправить с помощью Manifest s, чтобы обойти стирание типа:

class Job[T <: Event : ClassManifest] {
  val clazz: Class[T] = implicitly[ClassManifest[T]].asInstanceOf[Class[T]]
  var steps = List[(T => Unit)]()

  def addStep(step: (T => Unit)) {
    steps = step :: steps
  }

  def processEvent1(event: Event): Boolean = {
    try {
      processEvent(clazz.cast(event))
    }
    catch {
      case e: ClassCastException => false
    }
  }

  def processEvent(event: T): Boolean = {
    steps.foreach(_.apply(event))
    return true
  }
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...