2015-05-09 89 views
4

我有這是用Java編寫的,有數以百計的代碼重複就像一個巨大的統一代碼工作:通Java的方法調用/ Scala的類方法

createButtonOne() { 
    ... 
    public boolean pressed() { 
     doSomething(); 
     return true; 
    } 
} 

createButtonTwo() { 
    ... 
    public boolean pressed() { 
     doAnotherThing(); 
     return true; 
    } 
} 

代碼字面上是相同的除了被調用的函數之外,它很煩人。當然,我可以將這些方法的很大部分外包,但這會花費我更多的時間,而不是使用更好的工具來完成。或者我想。

我想要做的是這樣的:

ScalaButton buttonOne = new ScalaButton(); 
buttonOne.create("Label", Controller.doSomething()); 

ScalaButton buttonTwo = new ScalaButton(); 
buttonTwo.create("Label2", Controller.doAnotherThing()); 

所以我創建ScalaButton如下:

class ScalaButton 
{ 
    def create(label:String, action:() => Unit): Unit = 
    { 
     val button:Button = singletonCreator.createButton(label); 
     button.addListener(new InputListener() 
     { 
      override def pressed(...) 
      { 
       action() 
       true 
      } 
     } 
} 

的問題是,我從來沒有做過從Java這個調用,它說

找到void,required scala.Function0

所以我想知道,是否有可能通過這種(或另一種)方式向Scala傳遞一個java方法調用?我沒有在幾個月內與Java合作過,也沒有用這種方式和Scala一起使用它...

+0

控制器是用Java還是Scala編寫的? –

+0

@EdStaub目前所有東西都是用Java編寫的。 – Sorona

+0

@SethTisue Scala和Java都已經進化了2011年,所以我沒有看到重複。我仔細看過你之前發佈的問題。 – Sorona

回答

2

它不會編譯,因爲您沒有將方法傳遞給,您傳遞的結果是方法調用,即void

如果您想從Java向Scala傳遞函數,則需要構造一個實例 - 在本例中爲AbstractFunction0<BoxedUnit>,它對應於() => Unit

要做到這一點,你需要:

import scala.AbstractFunction0 
import scala.runtime.BoxedUnit 

然後:

buttonOne.create("Label", new AbstractFunction0<BoxedUnit>() { 
    @Override 
    public BoxedUnit apply() { 
     Controller.doSomething() 
     return BoxedUnit.UNIT; 
    } 
}); 

還有一個Function0<BoxedUnit>,但你不想使用它 - 它並非是用Java構建。

正如你所看到的,它不是直接使用。如果你使用Java 8,你可以簡化這一點。

你需要像這樣定義一個函數:

private static Function0<BoxedUnit> getBoxedUnitFunction0(Runnable f) { 
    return new AbstractFunction0<BoxedUnit>() { 

      @Override 
      public BoxedUnit apply() { 
       f.run(); 
       return BoxedUnit.UNIT; 
      } 
     }; 
} 

不要忘了import scala.Function0 - 這不是建造,所以沒關係。現在你可以這樣使用它:

buttonOne.create("Label", getBoxedUnitFunction0(Controller::doSomething)); 
+1

因此,如果不使用Java 8,我會用其他(相當無用的)內聯函數替換數十個(而非無用的)內聯函數?我想要這個抽象像「buttonOne.create(」標籤「,方法()」),而不必再定義回調:(:(因爲我看到這一點,用這種方法我沒有獲得_anything_ :() – Sorona

+0

不幸的是,只有Java 8支持方法引用(如'Controller :: doSomething')。Java沒有理解Scala的抽象。 –

+0

這非常不幸,但非常感謝您的澄清。提醒我總是使用Scala來處理我自己的(和/或新的)項目:) – Sorona