Using Scala from Java: passing functions as parameters

前端 未结 4 2060
陌清茗
陌清茗 2020-12-01 07:12

Consider the following Scala code:

package scala_java
object MyScala {
  def setFunc(func: Int => String) {
    func(10)
  }
}

Now in Ja

相关标签:
4条回答
  • 2020-12-01 07:46

    The easiest way for me is to defined a java interface like:

    public interface JFunction<A,B> {
      public B compute( A a );
    }
    

    Then modify your scala code, overloading setFunc to accept also JFunction objects such as:

    object MyScala {
      // API for scala
      def setFunc(func: Int => String) {
        func(10)
      }
      // API for java
      def setFunc(jFunc: JFunction[Int,String]) {
        setFunc( (i:Int) => jFunc.compute(i) )
      }
    }
    

    You will naturally use the first definition from scala, but still be able to use the second one from java:

    public class MyJava {
      public static void main(String [] args) {
        MyScala.setFunc(myFunc);  // This line gives an error
      }
    
      public static final JFunction<Integer,String> myFunc = 
        new JFunction<Integer,String>() {
          public String compute( Integer a ) {
            return String.valueOf(a);
          }
        };
    
    }
    
    0 讨论(0)
  • 2020-12-01 07:57

    Here's my attempt at a solution, a little library: https://github.com/eirslett/sc8

    You wrap your Java 8 lambda in F(...) and then it's converted to a Scala function.

    0 讨论(0)
  • 2020-12-01 08:06

    You have to manually instantiate a Function1 in Java. Something like:

    final Function1<Integer, String> f = new Function1<Integer, String>() {
        public int $tag() {
            return Function1$class.$tag(this);
        }
    
        public <A> Function1<A, String> compose(Function1<A, Integer> f) {
            return Function1$class.compose(this, f);
        }
    
        public String apply(Integer someInt) {
            return myFunc(someInt);
        }
    };
    MyScala.setFunc(f);
    

    This is taken from Daniel Spiewak’s “Interop Between Java and Scala” article.

    0 讨论(0)
  • 2020-12-01 08:06

    In the scala.runtime package, there are abstract classes named AbstractFunction1 and so on for other arities. To use them from Java you only need to override apply, like this:

    Function1<Integer, String> f = new AbstractFunction1<Integer, String>() {
        public String apply(Integer someInt) {
            return myFunc(someInt);
        }
    };
    

    If you're on Java 8 and want to use Java 8 lambda syntax for this, check out https://github.com/scala/scala-java8-compat.

    0 讨论(0)
提交回复
热议问题