我可以让Scala更喜欢隐式转换为Java8Lambda吗?

我可以让Scala更喜欢隐式转换为Java8Lambda吗?,scala,java-8,implicit-conversion,Scala,Java 8,Implicit Conversion,我正在为kafka streams库编写Scala包装器。基本方法是提供从kafka streams类(如KStream)到richKStreamOps类的隐式转换 例如,KStream提供以下map签名: <K1, V1> KStream<K1, V1> map(KeyValueMapper<K, V, KeyValue<K1, V1>> mapper) 请注意,map这里需要一个函数返回一个Tuple2,并处理将其转换为特定于kafka流的K

我正在为kafka streams库编写Scala包装器。基本方法是提供从kafka streams类(如
KStream
)到rich
KStreamOps
类的隐式转换

例如,
KStream
提供以下
map
签名:

<K1, V1> KStream<K1, V1> map(KeyValueMapper<K, V, KeyValue<K1, V1>> mapper)
请注意,
map
这里需要一个函数返回一个
Tuple2
,并处理将其转换为特定于
kafka流的
KeyValue
类型,这样用户就不需要直接与
KeyValue
交互

我提供了一个隐式转换:

implicit def ops[K, V](kstream: KStream[K, V]): KStreamOps[K, V] = new KStreamOps[K, V](kstream)
但当我尝试在如下代码中使用新的
映射时:

val inputStream: KStream[Int, String] = builder.stream(inputTopic)
stream.map{ (k, v) => (k, v) }
我收到以下编译错误:

[error] KStreamOpsTest.scala:47: type mismatch;
[error]  found   : (Int, String)
[error]  required: org.apache.kafka.streams.KeyValue[Int,String]
[error]       stream.map((k, v) => (k, v))
[error]                            ^
[error] KStreamOpsTest.scala:47: Could not derive subclass of org.apache.kafka.streams.kstream.KeyValueMapper[Int,String,org.apache.kafka.streams.KeyValue[Int,String]]
[error]  (with SAM `def method apply(x$1: Int, x$2: String)org.apache.kafka.streams.KeyValue[Int,String]`)
[error]  based on: ((k: Int, v: String) => scala.Tuple2(k, v)).
[error]       stream.map((k, v) => (k, v))
因此,编译器尝试使用
KStream#map
使用期望
KeyValue
返回的SAM,而不是期望函数输出为
Tuple2
的my
KStreamOps#map

如果我将我的方法重命名为
KStreamOps#map1
并调用
stream.map1
,隐式转换将按预期工作,代码将编译

为什么编译器不能识别出存在一个隐式转换,该转换将得到一个具有正确签名的函数的方法?是否不考虑函数返回类型?山姆会永远赢吗


我正在用Scala 2.11.8测试这一点,启用了
-Xexperimental
标志。

正如@ukasz所建议的,创建显式包装器似乎是一种方法。我可能会提供一个从包装类型到
KStream
的隐式转换:

implicit def unwrap[K, V](wrapped: WrappedKStream[K, V]): KStream[K, V] = wrapped.underlying
这样,我们就可以同时使用
KStream
和包装器的方法,但是包装器类方法具有优先权


这里一个明显的缺点是,用户在创建初始对象时需要显式使用包装器类型。

正如@ukasz所建议的,创建显式包装器似乎是一种方法。我可能会提供一个从包装类型到
KStream
的隐式转换:

implicit def unwrap[K, V](wrapped: WrappedKStream[K, V]): KStream[K, V] = wrapped.underlying
这样,我们就可以同时使用
KStream
和包装器的方法,但是包装器类方法具有优先权


这里一个明显的缺点是,用户在创建初始对象时需要显式使用包装器类型。

如果原始对象上已经存在
map
方法,编译器不会寻找到该方法的隐式转换。这就是算法的工作原理。除了重命名或创建自己的显式而非隐式创建的包装器类之外,我不知道如何解决这个问题。我想更全面地了解是什么决定了方法签名的唯一性。例如,我假设采用两个参数而不是一个参数的
map
方法不会与现有的
map
方法混淆,并且会触发查找隐式转换。我还假设接受非函数类型的
map(x:Int)
是不同的。这是真的吗?这里的特殊问题是类型擦除吗?签名编译为
map(f:Function)
,因此无法区分函数参数和返回类型?如果原始对象上已经存在
map
方法,编译器不会寻找隐式转换到该方法的对象。这就是算法的工作原理。除了重命名或创建自己的显式而非隐式创建的包装器类之外,我不知道如何解决这个问题。我想更全面地了解是什么决定了方法签名的唯一性。例如,我假设采用两个参数而不是一个参数的
map
方法不会与现有的
map
方法混淆,并且会触发查找隐式转换。我还假设接受非函数类型的
map(x:Int)
是不同的。这是真的吗?这里的特殊问题是类型擦除吗?签名编译为
map(f:Function)
,因此无法区分函数参数和返回类型?