2016-09-15 87 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