การส่งผ่านฟังก์ชัน Scala ไปยังวิธีการ Java 8


18

โค้ด Scala ต่อไปนี้ใช้งานได้และสามารถส่งผ่านไปยังเมธอด 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] = ???
}

นี่คือรอบที่สองของฉัน - มันใช้ wrapper ทั่วไปสำหรับส่วนต่อประสานฟังก์ชั่น Java-8 เพื่อทำให้ไวยากรณ์ของ Scala ง่ายขึ้น:

// 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)

เราทำได้ดีกว่านี้ไหม

จากการติดตามมีโอกาสใดที่ Scala จะใช้ op-code แบบไดนามิกที่เรียกว่า Java 8 ในการใช้งานฟังก์ชั่นชั้นหนึ่งหรือไม่? มันจะทำให้ทุกอย่างใช้งานได้อย่างน่าอัศจรรย์หรือว่าจะต้องมีการแปลงประโยคหรือไม่

คำตอบ:


10

คุณสามารถแปลงเป็นนัยได้:

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

คุณไม่ควรจะต้องจริงแทนที่composeและandThenแต่บางที Scala คอมไพเลอร์ไม่ทราบเกี่ยวกับ Java วิธีการอินเตอร์เฟซที่ 8 เริ่มต้นเลย (แก้ไข: ควรทำงานใน 2.10.3.)

นอกจากนี้คุณควรจะสามารถที่จะกำหนด lambdas สกาล่า (คือx => ...) ไปFunctionและประเภท SAM อื่น ๆ ใน Scala 2.11 และ Java 8 lambdas Function1ไป (แก้ไข: เพิ่มได้จริงใน Scala 2.12 ไม่ใช่ 2.11)


you should be able to assign Scala lambdas- ซึ่งหมายความว่าใน Scala 2.11, ฟังก์ชั่น Scala สามารถส่งผ่านเป็นอาร์กิวเมนต์สำหรับ Java8 Lambda?
เควินเมเรดิ ธ

ไม่ว่าจะสามารถผ่านเป็นข้อโต้แย้งขึ้นอยู่กับประเภทของแลมบ์ดา; ถ้าเป็นเช่นjava.util.function.Consumer[scala.Function1[Integer, String]]นั้นก็สามารถทำได้ก่อน 2.11 เช่นกัน
Alexey Romanov
โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.