다음 스칼라 코드는 작동하며 함수를 기대하는 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) 할 필요가 없습니다 compose
및andThen
,하지만 어쩌면 스칼라 컴파일러는 아직 자바 (8) 기본 인터페이스 방법에 대해 알고하지 않습니다. (편집 : 2.10.3에서 작동해야합니다.)
또한, 스칼라 람다 (즉, 할당 할 수 있어야한다 x => ...
)에 Function
8 람다에 스칼라 2.11 및 Java와 다른 SAM 유형 Function1
. (편집 : 이것은 실제로 2.11이 아닌 Scala 2.12에서 추가되었습니다.)