Границы типа Scala в строителе - PullRequest
0 голосов
/ 29 июня 2018

Я думаю, что сузил свою проблему до следующего:

trait Thing

case class SpecificThing(i: Int) extends Thing

trait ThingSource[T <: Thing] {
  def  next: T
}

class SpecificThingSource() extends ThingSource[SpecificThing] {
  override def next = SpecificThing(1)
}

object ThingSource {
  def apply[A <: Thing, B <: ThingSource[A]](sourceType: String): B = {
    sourceType match {
      case "specific" => new SpecificThingSource()
    }
  }
}

val a = ThingSource("specific").next

Компилятор, кажется, доволен большей частью этого, за исключением части компоновщика. Здесь выдает эту ошибку:

Expression of type SpecificThingSource doesn't conform to the expected type B

Я ожидаю, что с SpecificThing, являющимся подтипом типа Thing, и SpecificThingSource, являющимся типом ThingSource[SpecificThing], нет места для двусмысленности. Что мне не хватает? Можно ли вообще использовать строителя таким образом? Или есть лучшие способы добиться того, чего я хочу?

1 Ответ

0 голосов
/ 29 июня 2018

Если вы хотите "вернуть подкласс ThingSource" , то вам нужно экзистенциальное , а не универсальное количественное определение:

  def apply(sourceType: String)
  : B forSome { type B <: ThingSource[A] forSome { type A <: Thing}} = {
    sourceType match {
      case "specific" => new SpecificThingSource()
    }
  }

который можно записать короче как

  def apply(sourceType: String): ThingSource[_] = {
    sourceType match {
      case "specific" => new SpecificThingSource()
    }
  }
...