2016-09-15 88 views
1

我在Scala中编写了一个小型的JavaFx应用程序,我喜欢使用RxScala和RxJavaFx。用下面的代码,我收到了RxJavaObservable将RxJava Observable转换为RxScala Observable

JavaFxObservable.fromObservableValue(textfield.textProperty()) 

显然,正如我在斯卡拉写,我想有一个RxScalaObservable来代替。现在我找到了this post,说我要么直接导入隐式转换类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的集合(反之亦然),您有两个选项:JavaConvertersJavaConversions。前者引入了一个关键字asJava/asScala,而后者则相当于rx.lang.scala.JavaConversions,并为您隐式转换(如果您幸运的话!)。谷歌搜索这两个偏好,很显然,大多数人更喜欢JavaConvertersasScala关键字更明确的隐式转换。

问题2:有没有类似的结构像JavaConverters与RxScala?这将使上面这么多清洁的代码,我会说:

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

回答

0

这个问题是RxScala项目this pull request的出发点。

原始问题中提出的语法可以通过导入rx.lang.scala.JavaConverters来使用。

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

同样Scala的Observable可以转化成使用asJava一个Java Observable

另请参阅预期用途的examples

2

我会写你的例子如下:

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

其中Observable[String]是Scala的观测。 给予一个明确的类型为VAL texts确保英寸

为什么没有asScala隐式转换踢?

这就需要另一个隐含的包装类(让我们在PreScalaObservable调用),只叫toScala一个方法,所以,当你会写myJavaObservable.toScala,编译器会变成类似toPreScalaObservable(myJavaObservable).toScala

有两个包装类会有点混乱。或者如果你非常聪明,你实际上可以将asScala方法放到Scala Observable中,并像返回this一样实现它,并且由于Java Observable没有方法叫做asScala,所以myJavaObservable.toScala可以工作。但是,对于初学者来说,这可能相当复杂......

但是,如果您有更好的主意,或者知道如何简单介绍这一点,我鼓励您在RxScala issues中打开一个问题;该项目仍然在0.x,没有什么是石头...... ;-)

+0

说实话,我真的很喜欢所有运营商的链接。这是Rx API的定义权力之一(与Scala Collections API一样)。不得不引入额外的'val's,包括明确的输入,这并不是我特别喜欢在Scala中看到的东西。这是一个可行的把戏,这是一定的!我会进一步研究这个问题,并且肯定会考虑将这个讨论移到RxScala问题上。我想我可以在那边自己做拉请求。让我们继续坚持下去! – RvanHeest

0

为什么你需要将窗体RXJava转换为RXScala ?, RXScala具有RXJava所具有的所有功能。 例如

ZIP:

@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)); 
    } 

MERGE:

@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)) 
    } 

FLATMAP:

@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

+0

我真的不明白你的意思!你在争论“*为什么RxScala与RxJava具有完全相同的功能?*”?我之所以要问如何在RxJava和RxScala之间进行转换,是因为Java的lambda表达式与2.11中的Scala的lambda表达式不匹配,并且在代码中具有一致性(在应用程序中无处不在)也是一件好事。也许你可以更多地解释一下你想说的“为什么要转换”和“从头开始”。 – RvanHeest

+0

也许我不理解你,你使用JavaConverters是因为没有办法处理RXScala和JavaFxObservable相同吗?我建议使用RXScala,你可以做的和使用RxJava完全一样,所以不需要移植Java – paul

+0

的任何代码啊,这就是你的意思。事实上,在这种情况下,我通过RxJavaFx来解决这个问题,RxJavaFx将JavaFx UI事件封装在一个'Observable'(它本身非常有用!)中,但我想到的是一个通用API,它为我提供了一个RxJava'Observable',需要将其转换为RxScala'Observable'。我完全承认RxScala本身就是RxJava库的Scala包装,但如果你在Scala编写的话,它有一些与RxScala更好的结合。例如,我之前提到的lambda的区别... – RvanHeest