Как определить неявный класс, который может сводить как базовый, так и производный класс - PullRequest
0 голосов
/ 19 октября 2018

Как мне определить неявный класс, который может объединять как базовый, так и производный класс?

Я хочу реализовать класс, который бы объединял Flow и Source .Я попробовал это

implicit class FlowOpsMatExt[T, Mat](val flow: FlowOpsMat[T, Mat]) {
  def groupSortedByKey[K](keyForItem: T ⇒ K, maxBufferSize: Int): flow.Repr[Vector[T]]
}

Но вызвал экземпляр Source[] Я получил FlowOpsMat, который я больше не могу использовать в качестве источника.Поэтому я попытался обмануть его

implicit class FlowOpsMatExt[T, Mat, C <: FlowOpsMat[T, Mat]](val flow2: C)

, но он по какой-то причине не может определить типы.При явном вызове

new FlowOpsMatExt(source_instance)

я получаю следующую ошибку

Error:(106, 5) inferred type arguments [Nothing,Nothing,akka.stream.scaladsl.Source[akka.util.ByteString,akka.NotUsed]] do not conform to class FlowOpsMatExt's type parameter bounds [T,Mat,C <: akka.stream.scaladsl.FlowOpsMat[T,Mat]]
    new FlowOpsMatExt(src)

Минимальный воспроизводимый пример: https://gist.github.com/931a313546f14e809b705e86743dcdb0

Компилируется, если я явно указываю все типы new FlowOpsMatExt[ByteString, NotUsed, Source[ByteString, NotUsed]](src)но это убивает выгоду от использования неявного класса.

Чего мне не хватает?

Лучшее, что я могу придумать, - это сохранить реализацию функции расширения в абстрактном классе и реализовать из нее два неявных класса.

abstract class FlowOpsMatExt[T, Mat, C <: FlowOpsMat[T, Mat]] {
  protected val flow: C
}

implicit class FlowExt2[In, Out, Mat](val flow: Flow[In, Out, Mat]) extends FlowOpsMatExt[Out, Mat, Flow[In, Out, Mat]] {
}

implicit class SourceExt[T, Mat](val flow: Source[T, Mat]) extends FlowOpsMatExt[T, Mat, Source[T, Mat]] {
}

1 Ответ

0 голосов
/ 30 октября 2018

Из документации :

Опытные пользователи Scala могут задаться вопросом, возможно ли написать методы расширения, которые обогащают FlowOps для обеспечения более приятного синтаксиса.Короткий ответ заключается в том, что Scala 2 не поддерживает это полностью универсальным образом, проблема в том, что невозможно абстрагироваться от типа потока, который расширяется, потому что Source, Flow и SubFlow отличаются поколичество и вид параметров их типа.Хотя можно было бы написать неявный класс, который обогащает их в общем, этот класс потребовал бы явного создания экземпляра со всеми параметрами типа из-за SI-2712 .Частичный обходной путь, объединяющий расширения для источника и потока, см. в этом наброске Р. Куна .

...

Интересно отметить, что упрощенная формаэта проблема нашла свое применение в dotty test suite .Dotty - это версия Scala для разработчиков на пути к Scala 3.

...