스칼라 함수를 Java 8 메소드에 전달 깔끔한 방법이 있습니까? 첫

다음 스칼라 코드는 작동하며 함수를 기대하는 Java 메소드로 전달 될 수 있습니다. 더 깔끔한 방법이 있습니까? 첫 번째 패스는 다음과 같습니다.

val plusOne = new java.util.function.Function[Int,Int] {
  override def apply(t:Int):Int = t + 1

  override def andThen[V](after:function.Function[_ >: Int, _ <: V]):
    function.Function[Int, V] = ???

  override def compose[V](before:function.Function[_ >: V, _ <: Int]):
    function.Function[V, Int] = ???
}

두 번째 단계는 다음과 같습니다. Java-8 함수 인터페이스에 일반 래퍼를 사용하여 스칼라 구문을 더 간단하게 만듭니다.

// Note: Function1 is Scala's functional interface,
// Function (without the 1) is Java 8's.
case class JavaFunction1[U,V](f:Function1[U,V]) extends Function[U,V] {
  override def apply(t: U): V = f(t)
  override def compose[T](before:Function[_ >: T, _ <: U]):
    Function[T, V] = ???
  override def andThen[W](after:Function[_ >: V, _ <: W]):
    Function[U, W] = ???
}

val plusOne = JavaFunction1((x:Int) => x + 1)
val minusOne = JavaFunction1((x:Int) => x - 1)

더 잘할 수 있을까요?

후속 조치로, 스칼라가 언젠가 Java 8이 일급 함수 응용 프로그램에서와 같이 invoke-dynamic op-code를 사용할 가능성이 있습니까? 모든 것이 마술처럼 작동할까요? 아니면 여전히 구문 변환이 필요합니까?



답변

변환을 암시 적으로 만들 수 있습니다.

implicit def toJavaFunction[U, V](f:Function1[U,V]): Function[U, V] = new Function[U, V] {
  override def apply(t: U): V = f(t)

  override def compose[T](before:Function[_ >: T, _ <: U]):
    Function[T, V] = toJavaFunction(f.compose(x => before.apply(x)))

  override def andThen[W](after:Function[_ >: V, _ <: W]):
    Function[U, W] = toJavaFunction(f.andThen(x => after.apply(x)))
}

implicit def fromJavaFunction[U, V](f:Function[U,V]): Function1[U, V] = f.apply

당신은 실제로 오버라이드 (override) 할 필요가 없습니다 composeandThen ,하지만 어쩌면 스칼라 컴파일러는 아직 자바 (8) 기본 인터페이스 방법에 대해 알고하지 않습니다. (편집 : 2.10.3에서 작동해야합니다.)

또한, 스칼라 람다 (즉, 할당 할 수 있어야한다 x => ...)에 Function8 람다에 스칼라 2.11 및 Java와 다른 SAM 유형 Function1. (편집 : 이것은 실제로 2.11이 아닌 Scala 2.12에서 추가되었습니다.)