使用函数引用在Kotlin中重写Java代码发生SAM类型冲突 [英] Rewrite Java code in Kotlin using Function Reference occurs SAM types conflict

查看:1955
本文介绍了使用函数引用在Kotlin中重写Java代码发生SAM类型冲突的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我有一个使用方法引用的Java代码示例,我想将其重写为Kotlin。 Java版本使用方法参考,解决方案简短明了。但另一方面,我不能在Kotlin中使用方法参考。我设法编写的唯一版本如下所示。它似乎是 Function3 {s:String,b:Boolean,i:Int - >组合(s,b,i)} 可以用更干净的方式编写(如果可能的方法参考将是完美的)。

I have an example Java code using method reference that I want to rewrite to Kotlin. Java version is using method reference, solution is short and clear. But on the other hand I cannot use method reference in Kotlin. The only version that I've managed to write is one presented below. It seems like Function3 { s: String, b: Boolean, i: Int -> combine(s, b, i) } could be written in cleaner way (if possible method reference would be perfect).

我是Kotlin新手,所以我会感激任何线索。

I'm new to Kotlin so I'll be grateful for any clues.

Java

import io.reactivex.Observable;

public class TestJava {

    Observable<String> strings() {
        return Observable.just("test");
    }

    Observable<Boolean> booleans() {
        return Observable.just(true);
    }

    Observable<Integer> integers() {
        return Observable.just(1);
    }

    void test() {
        Observable.combineLatest(strings(), booleans(), integers(),
                this::combine);
    }

    double combine(String s, boolean b, int i) {
        return 1.0;
    }
}

Kotlin

import io.reactivex.Observable
import io.reactivex.functions.Function3

class TestKotlin {

    fun strings(): Observable<String> {
        return Observable.just("test")
    }

    fun booleans(): Observable<Boolean> {
        return Observable.just(true)
    }

    fun integers(): Observable<Int> {
        return Observable.just(1)
    }

    fun test() {
        Observable.combineLatest(strings(), booleans(), integers(),
                Function3 { s: String, b: Boolean, i: Int -> combine(s, b, i) })
    }

    fun combine(s: String, b: Boolean, i: Int): Double {
        return 1.0
    }
}

编辑

以下方法参考Kotlin会出错。

Following method references in Kotlin gives an error.

fun test() {
    Observable.combineLatest(strings(), booleans(), integers(), this::combine)
}

fun test() {
    Observable.combineLatest(strings(), booleans(), integers(), TestKotlin::combine)
}




使用
提供的参数,不能调用以下任何函数:@CheckReturnValue @SchedulerSupport public final fun combineLatest(p0:((观察者) - >单位)!,p1 :((观察者) - >单位)! ,p2:
((观察员) - >单位)!,p3:((???,???,???) - > ???)!):
Observable<(? ?? .. ???)>!在io.reactivex.Observable中定义
@CheckReturnValue @SchedulerSupport public open fun combineLatest(p0:ObservableSource!,p1:ObservableSource!,p2:
ObservableSource!,p3:io.reactivex.functions.Function3!) :
Observable<(??? ??? ???)>!在io.reactivex.Observable中定义
@CheckReturnValue @SchedulerSupport public open fun combineLatest(p0:Function!,out
(??? .. ???)>!,p1:Int,vararg p2: ObservableSource!):
Observable<(??? ??? ???)>!在io.reactivex.Observable中定义

None of the following functions can be called with the arguments supplied: @CheckReturnValue @SchedulerSupport public final fun combineLatest(p0: ((Observer) -> Unit)!, p1: ((Observer) -> Unit)!, p2: ((Observer) -> Unit)!, p3: ((???, ???, ???) -> ???)!): Observable<(???..???)>! defined in io.reactivex.Observable @CheckReturnValue @SchedulerSupport public open fun combineLatest(p0: ObservableSource!, p1: ObservableSource!, p2: ObservableSource!, p3: io.reactivex.functions.Function3!): Observable<(???..???)>! defined in io.reactivex.Observable @CheckReturnValue @SchedulerSupport public open fun combineLatest(p0: Function!, out (???..???)>!, p1: Int, vararg p2: ObservableSource!): Observable<(???..???)>! defined in io.reactivex.Observable

编辑2

RxKotlin 解决了答案中提到的问题。

RxKotlin solves issue mentioned in answer.

import io.reactivex.rxkotlin.Observables

class TestKotlin {

    fun test() {
        Observables.combineLatest(strings(), booleans(), integers(), this::combine)
    }

}


推荐答案

您还可以使用函数引用表达式就像Java中的方法引用表达式一样。例如,Kotlin中的组合函数引用为 KFunction3 ,如下所示:

You can also using Function Reference Expression in Kotlin just like as Method Reference Expression in Java. for example, the combine function reference as KFunction3 in Kotlin as below:

val f: kotlin.reflect.KFunction3<String, Boolean, Int, Double> = this::combine

在java中,Method Reference Expression可以分配给任何兼容的 功能界面,但你可以不要将函数参考表达式分配给任何函数类型,即使它们是兼容,例如:

In java, Method Reference Expression can assign to any compatible Functional Interface, but you can't assign a Function Reference Expression to any Function types even if they are compatible, for example:

val f:io.reactivex.functions.Function3<String,Boolean,Int,Double> =this::combine
//                                                type mismatch error     ---^

确实,Kotlin使用 SAM转换转换lambda / 函数引用表达式到Java的实现功能界面,这意味着Kotlin的功能如下:

Indeed, Kotlin using SAM Conversions to convert lambda/Function Reference Expression into an implementation of Java Functional Interface, which means Kotlin does something like as below:

fun test() = TODO()

val exector:Executor = TODO()

exector.execute(::test)

//::test compile to java code as below:
Runnable task = new Runnable(){
   public void run(){
      test();
   }
};

为什么方法参考表达式可以在Java中正常工作,但使用< Kotlin中的href =https://kotlinlang.org/docs/reference/reflection.html#function-references =nofollow noreferrer>函数参考表达式失败了吗?

Why did Method Reference Expression can works fine in Java, but using Function Reference Expression is failed in Kotlin?

基于上面的内容,您可以看到 combineLatest 方法class =post-tagtitle =show questions标记为'rx-java2'rel =tag> rx-java2 。例如,以下两个不能使用函数参考表达式正确:

Base on the above, and you can see there are many overloaded combineLatest methods in rx-java2. for example, the following two can't make Kotlin using Function Reference Expression correctly:

combineLatest(
       ObservableSource<out T1>,
       ObservableSource<out T2>,
       ObservableSource<out T3>, 
       Function3<T1, T2, T3, out R>
)

combineLatest(
       ObservableSource<out T1>,
       ObservableSource<out T2>,
       ObservableSource<out T3>, 
       ObservableSource<out T4>, 
       Function4<T1, T2, T3, T4, out R>
)

正如我所说,Kotlin使用 SAM转换转换lambda / 函数引用表达式到Java 功能界面,但它无法分配给Java 功能界面直接。

As I said Kotlin using SAM Conversions to convert a lambda/Function Reference Expression to a Java Functional Interface, but it can't assign to a Java Functional Interface directly.

combineLatest 方法的第4个参数Kotlin,编译器根本无法推断它的类型,因为第4个参数类型可以是 io.reactivex.functions.Function3 ObservableSource 。因为 ObservableSource 也是Java 功能界面

The 4th parameter of the combineLatest method in Kotlin, the compiler can't infer its type at all, since the 4th parameter type can be io.reactivex.functions.Function3 or ObservableSource. because ObservableSource is also a Java Functional Interface.

当你遇到 SAM转换就像这样冲突,您可以使用适配器函数将lambda转换为特定的SAM类型,例如:

When you meet SAM Conversion conflict like as this, you can using an adapter function that converts a lambda to a specific SAM type, for example:

typealias RxFunction3<T1, T2, T3, R> = io.reactivex.functions.Function3<T1,T2,T3,R>

val f: RxFunction3<String, Boolean, Int, Double> = RxFunction3{ s, b, i-> 1.0}

因此在使用lambda / 函数引用表达式,例如:

So you must using an adaption before using lambda/Function Reference Expression, for example:

typealias RxFunction3<T1, T2, T3, R> = io.reactivex.functions.Function3<T1,T2,T3,R>

fun <T1,T2,T3,R> KFunction3<T1,T2,T3,R>.toFunction3(): RxFunction3<T1, T2,T3,R> {
    return RxFunction3 { t1, t2, t3 -> invoke(t1, t2, t3) }
}

然后您可以使用函数参考表达式,如下所示: / p>

Then you can using Function Reference Expression as below, for example:

Observable.combineLatest(
        strings(),
        booleans(), 
        integers(), 
        //             v--- convert KFunction3 to RxFunction3 explicitly
        this::combine.toFunction3()
)

这篇关于使用函数引用在Kotlin中重写Java代码发生SAM类型冲突的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆