Convierta la unidad Scala en Java Void
type-conversion typesafe (3)
Tengo una clase Java que toma la
Function[String, Void]
, que es similar aConsumer
interfaz funcional delConsumer
.
Entonces esta clase debería usar Consumer
. Para una primera aproximación, la Function<String, Void>
nunca es el tipo correcto de usar. Si no puede cambiarlo, al menos tenga en cuenta que es un mal diseño y tenga cuidado con esta biblioteca. La respuesta de Som-snytt ya muestra cómo llamar correctamente la temp
desde Scala, y es simple escribir una conversión implícita de String => Unit
a Function[String, Void]
si lo desea. Así que el resto de esta respuesta se trata de por qué tus otros intentos no funcionaron.
ya que es equivalente anulado
Precisamente: es equivalente a void
, no Void
. El código Java equivalente llamaría a un método void
, por ejemplo, Consumer.accept
:
public void tempOfVoid(Consumer<String> f) {
temp(new Function<String, Void> {
public Void apply(String x) {
return f.accept(x);
}
};
}
y no podrá verificar el tipo. En cambio, necesitas
public Void apply(String x) {
f.accept(x);
return null;
}
lo mismo que se muestra en Scala por la respuesta de som-snytt.
Ahora, puede preguntar: ¿qué sucede cuando Unit
es un argumento de tipo, porque void
no puede ser, o cuando el valor de tipo Unit
necesita ser representado en tiempo de ejecución (un ejemplo sería val x: Any = ()
)? En esos casos, la Unit
está representada por la clase scala.runtime.BoxedUnit
, al igual que Int
se suele traducir a int
pero a veces a java.lang.Integer
. Esto explica por qué el lanzamiento a Void
arroja una excepción (y no da como resultado un error de compilación). Void
no es una traducción adecuada para estos casos porque no tiene valores (no null
) mientras que Unit
tiene exactamente uno: ()
.
Tengo una clase Java que toma la Function[String, Void]
, que es similar a Consumer
interfaz funcional del Consumer
. Estoy llamando a esta función de Java desde el código de Scala. Como puede ver a continuación, acepto la function: => Unit
en el lado de Scala ya que es equivalente anulada. Cuando intento aplicar esta función en lugar del tipo de devolución de Void
ocurre una discrepancia. La conversión explícita de .asInstanceOf[Void]
también arrojó una excepción. ¿Cómo convertimos => Unit
a => Void
?
// Java
class AcceptFunction {
public void temp(Function<String, Void> f) {
f.apply("Hello");
}
}
// Scala
def temp(f: String => Unit): Unit = {
new AcceptFunction().temp(new Function[String, Void]() {
override def apply(t: String): Void = f(t) // <===== error expecting Void instead of Unit
})
}
Aparentemente,
scala> new jfunc.Acceptor().f(s => println(s))
<console>:12: error: type mismatch;
found : Unit
required: Void
new jfunc.Acceptor().f(s => println(s))
^
scala> new jfunc.Acceptor().f { s => println(s) ; null }
hello, world.
donde la java es como usted muestra:
package jfunc;
import java.util.function.*;
public class Acceptor {
public void f(Function<String, Void> g) { g.apply("hello, world."); }
}
lo hace:
scala> :javap -c -
public static final java.lang.Void $anonfun$res0$1(java.lang.String);
Code:
0: getstatic #33 // Field scala/Predef$.MODULE$:Lscala/Predef$;
3: aload_0
4: invokevirtual #37 // Method scala/Predef$.println:(Ljava/lang/Object;)V
7: aconst_null
8: areturn
public $line3.$read$$iw$$iw$();
Code:
0: aload_0
1: invokespecial #39 // Method java/lang/Object."<init>":()V
4: aload_0
5: putstatic #41 // Field MODULE$:L$line3/$read$$iw$$iw$;
8: aload_0
9: new #43 // class jfunc/Acceptor
12: dup
13: invokespecial #44 // Method jfunc/Acceptor."<init>":()V
16: invokedynamic #63, 0 // InvokeDynamic #0:apply:()Ljava/util/function/Function;
21: invokevirtual #67 // Method jfunc/Acceptor.f:(Ljava/util/function/Function;)V
24: getstatic #72 // Field scala/runtime/BoxedUnit.UNIT:Lscala/runtime/BoxedUnit;
27: putfield #74 // Field res0:Lscala/runtime/BoxedUnit;
30: return
Debe usar el tipo de consumidor no Function
, ya que su Function
no tiene salida, y el Consumer
se utiliza para este escenario. me gusta:
class AcceptFunction {
public void temp(Consumer<String> f) { // Consumer for no output Function
f.accept("Hello");
}
}
def temp(f: String => Unit): Unit = {
new AcceptFunction().temp(new Consumer[String]() {
override def accept(t: String): Unit= f(t)
})
}