Сигнатура метода конфликтует, когда класс и его параметры выходят из одной черты - PullRequest
0 голосов
/ 17 апреля 2019

Извиняюсь за слегка расплывчатый заголовок, было трудно попытаться обобщить мою проблему в одну строку. Надеясь, что следующие фрагменты кода лучше объясняют мои намерения.

Давайте начнем с введения черты для всех вещей, которые Reduceable:

trait Reduceable[A] {
  def reduceWith(other: A): A
} 

Примерами таких Reduceable вещей могут быть счетчики как таковые:

case class GenderCounter(male: Int, female: Int)
    extends Reduceable[GenderCounter] {
  override def reduceWith(other: GenderCounter): GenderCounter =
    GenderCounter(male + other.male, female + other.female)
}

case class FruitCounter(apples: Int, oranges: Int)
    extends Reduceable[FruitCounter] {
  override def reduceWith(other: FruitCounter): FruitCounter =
    FruitCounter(apples + other.apples, oranges + other.oranges)
}

GenderCounter(5, 10) reduceWith GenderCounter(4, 11)
// res: GenderCounter = GenderCounter(9,21)

Класс с указанными выше счетчиками в качестве параметров тоже может быть Reduceable

case class CompoundCounter(c1: GenderCounter, c2: FruitCounter)
    extends Reduceable[CompoundCounter] {
  override def reduceWith(
    other: CompoundCounter)
    : CompoundCounter = CompoundCounter(
    c1 reduceWith other.c1,
    c2 reduceWith other.c2
  )
}

CompoundCounter(GenderCounter(5, 10), FruitCounter(11, 2)) reduceWith CompoundCounter(GenderCounter(5, 10), FruitCounter(11, 2))
// res: CompoundCounter = CompoundCounter(GenderCounter(10,20),FruitCounter(22,4))

Однако возникает проблема, когда я пытаюсь ввести универсальный Reduceable класс , где его параметры также являются общими Reduceable s

case class CollectionReduceable[A, B](r1: Reduceable[A], r2: Reduceable[B])
    extends Reduceable[CollectionReduceable[A, B]] {
  override def reduceWith(
    other: CollectionReduceable[A, B])
    : CollectionReduceable[A, B] = CollectionReduceable(
    r1 reduceWith other.r1, 
    r2 reduceWith other.r2
  )
}

// error: type mismatch
// found   : other.r1.type (with underlying type Reduceable[A])
// required: A
//           r1 reduceWith other.r1,

// Desired outcome: same as CompoundCounter

Я получаю источник сообщения об ошибке, потому что сигнатура черты reduceWith вызывает other: A, но если я ее изменю, то GenderCounter и FruitCounter сломаются. Что может изменить я, чтобы достичь желаемого результата? Спасибо !!

1 Ответ

4 голосов
/ 17 апреля 2019

Попробуйте

case class CollectionReduceable[A <: Reduceable[A], B <: Reduceable[B]](r1: A, r2: B) extends Reduceable[CollectionReduceable[A, B]] {
  override def reduceWith(other: CollectionReduceable[A, B]): CollectionReduceable[A, B] =
    CollectionReduceable(
      r1.reduceWith(other.r1),
      r2.reduceWith(other.r2)
    )
  }

CollectionReduceable(GenderCounter(5, 10), FruitCounter(11, 2)) reduceWith CollectionReduceable(GenderCounter(5, 10), FruitCounter(11, 2))
// CollectionReduceable(GenderCounter(10,20),FruitCounter(22,4))
...