Конвертировать RxJava Observable в RxScala Observable

Я пишу небольшое приложение JavaFx на Scala, и мне нравится использовать для этого RxScala и RxJavaFx. С помощью следующего кода я получаю RxJava Observable:

JavaFxObservable.fromObservableValue(textfield.textProperty())

Очевидно, поскольку я пишу на Scala, вместо этого я хотел бы иметь RxScala Observable. Теперь я нашел этот пост, говоря, что мне нужно либо импортировать класс неявного преобразования JavaConversions._, либо вызвать toScalaObservable напрямую. Однако первый вариант мне не подходит, а второй вариант выглядит некрасиво:

Вариант 1:

import rx.lang.scala.JavaConversions._
JavaFxObservable.fromObservableValue(textfield.textProperty())
  .map(s => /* do something */)

Это не работает, так как RxJava также предлагает оператор map, хотя тип аргумента технически отличается.

Вариант 2:

import rx.lang.scala.JavaConversions._
toScalaObservable(JavaFxObservable.fromObservableValue(textfield.textProperty()))
  .map(s => /* do something */)

Это работает, но будьте честны, это выглядит просто ужасно!

Вопрос 1. Я что-то упустил или это действительно единственные два варианта?

Я имею в виду, что для преобразования стандартных коллекций Java в коллекции Scala (и наоборот) у вас есть два варианта: JavaConverters и JavaConversions. Первый вводит ключевое слово asJava/asScala, тогда как второй эквивалентен rx.lang.scala.JavaConversions и неявно выполняет преобразование за вас (если вам повезет!). Погуглив предпочтения этих двух, становится ясно, что большинство людей предпочитают более явное неявное преобразование из JavaConverters с ключевым словом asScala.

Вопрос 2. Существует ли конструкция, похожая на JavaConverters, в RxScala? Это сделало бы приведенный выше код намного чище, я бы сказал:

import rx.lang.scala.JavaConverters._ // this class doesn't exist!
JavaFxObservable.fromObservableValue(textfield.textProperty())
  .asScala
  .map(s => /* do something */)

person RvanHeest    schedule 15.09.2016    source источник


Ответы (3)


Я бы написал ваш пример следующим образом:

import rx.lang.scala.JavaConversions._
val texts: Observable[String] = JavaFxObservable.fromObservableValue(textfield.textProperty())
texts.map(s => /* do something */)

где Observable[String] — Scala Observable. Предоставление явного типа для val texts гарантирует, что неявное преобразование сработает.

Почему нет asScala?

Для этого потребуется еще один неявный класс-оболочка (давайте вызовем PreScalaObservable) только с одним методом с именем toScala, так что когда вы напишете myJavaObservable.toScala, компилятор превратит его во что-то вроде toPreScalaObservable(myJavaObservable).toScala.

Наличие двух классов-оболочек было бы немного запутанным. Или, если вы очень сообразительны, вы можете поместить метод asScala в Scala Observable и реализовать его так же, как возвращающий this, а поскольку в Java Observable нет метода с именем asScala, myJavaObservable.toScala будет работать. Но опять же, это может быть довольно сложно понять для начинающих...

Но если у вас есть идея получше или вы знаете, как это просто представить, я рекомендую вам открыть задачу в разделе . Проблемы с RxScala; проект все еще находится в 0.x, и ничего не высечено на камне... ;-)

person Samuel Gruetter    schedule 15.09.2016
comment
Если честно, мне очень нравится цепочка всех операторов. Это одна из определяющих возможностей Rx API (как и в случае с Scala Collections API). Необходимость вводить дополнительные val, включая явную типизацию, — это не то, что мне особенно нравится делать и видеть в Scala. Это трюк, который работает, это точно! Я посмотрю на это еще немного и определенно рассмотрю возможность переноса этого обсуждения на проблемы RxScala. Я предполагаю, что я тоже могу сделать запрос на включение там. Давайте держать в жестком на этом! - person RvanHeest; 16.09.2016

Зачем нужно было конвертировать RXJava в RXScala? RXScala имеет все те же функции, что и RXJava. Например

Почтовый индекс:

  @Test def zip(): Unit = {
    addHeader("Observable zip")
    Observable.just("hello")
      .zip(Observable.just(" scala"))
      .zip(Observable.just(" world!"))
      .map(s => s._1._1.concat(s._1._2).concat(s._2).toUpperCase)
      .subscribe(s => println(s));
  }

ОБЪЕДИНИТЬ:

  @Test def merge(): Unit = {
    addHeader("Observable merge")
    Observable.just("hello")
      .merge(Observable.just(" scala"))
      .merge(Observable.just(" world!"))
      .reduce((s, s1) => s.concat(s1))
      .map(s => s.toUpperCase).subscribe(s => println(s))
  }

ПЛОСКАЯ КАРТА:

  @Test def flatMap(): Unit = {
    addHeader("Flat Map")
    val text = "number mutated in flatMap::"
    val list = getList
    Observable.from(list)
      .flatMap(n => Observable.just(n) //--> New pipeline
        .map(n => text.concat(String.valueOf(n))))
      .map(s => s.toUpperCase())
      .subscribe(s => println(s))
  }

Я бы начал с нуля, чтобы быть честным с вами. Если вы хотите посмотреть другие примеры операторов, https://github.com/politrons/reactiveScala

person paul    schedule 23.09.2016
comment
Я действительно не понимаю, что вы имеете в виду! Вы спорите Зачем существует RxScala, если у него есть все те же функции, что и у RxJava?? Моя причина спросить, как преобразовать RxJava в RxScala, заключается в том, что лямбда-выражения Java не совпадают с лямбда-выражениями Scala с версии 2.11, а наличие согласованности в вашем коде (используйте RxScala везде в вашем приложении) также является хорошей вещью. Может быть, вы могли бы объяснить немного больше того, что вы хотели сказать, в разделе «Почему конвертировать и начинать с нуля». - person RvanHeest; 23.09.2016
comment
возможно, я вас не понял, вы используете JavaConverters, потому что нет возможности сделать с RXScala то же самое, что с JavaFxObservable? Я предполагал, что с RXScala вы можете делать то же самое, что и с RxJava, поэтому нет необходимости портировать какой-либо код с Java. - person paul; 23.09.2016
comment
Ах, вот что вы имеете в виду. Действительно, в этом случае я пришел к этой проблеме через RxJavaFx, который оборачивает события пользовательского интерфейса JavaFx в Observable (что само по себе очень полезно!), но я думал об общем API, который предоставляет мне RxJava Observable, который должен быть преобразован в RxScala Observable. Я полностью признаю тот факт, что RxScala сама по себе является оболочкой библиотеки RxJava для Scala, но в ней есть некоторые вещи, которые лучше работают с RxScala, если вы пишете на Scala. Например, разница в лямбдах, о которой я упоминал ранее... - person RvanHeest; 23.09.2016

Этот вопрос был отправной точкой для этого запроса на вытягивание в проекте RxScala.

Синтаксис, предложенный в исходном вопросе, можно использовать, импортировав rx.lang.scala.JavaConverters.

import rx.lang.scala.JavaConverters._
JavaFxObservable.fromObservableValue(textfield.textProperty())
  .asScala
  .map(s => /* do something */)

Точно так же Scala Observable можно преобразовать в Java Observable с помощью asJava.

См. также примеры использования по назначению.

person RvanHeest    schedule 29.09.2016