kFunction1中的kotlin泛型

ale*_*adr 2 generics kotlin

假设您有两个类TestA和TestB.假设TestA扩展了TestB:

public class TestB {
    private int intProp;
    public int getIntProp() {
        return intProp;
    }
    public void setIntProp(int intProp) {
        this.intProp = intProp;
    }
}


public class TestA extends TestB {
    private String strProp;
    public String getStrProp() {
        return strProp;
    }
    public void setStrProp(String strProp) {
        this.strProp = strProp;
    }
}
Run Code Online (Sandbox Code Playgroud)

现在我创建下一行代码:

var getter1: KFunction1<TestA, Int> = TestA::getIntProp
Run Code Online (Sandbox Code Playgroud)

正如你所看到的,我从TestB的TestA类方法访问:TestA :: getIntProp所以结果是KFunction1的实例,通用参数<TestA,Int>

现在我尝试创建下一行代码

var getter2: KFunction1<TestA, Int> = TestB::getIntProp
Run Code Online (Sandbox Code Playgroud)

它也可以工作和编译,而我希望会有编译错误

hot*_*key 6

这是Kotlin中的泛型差异,其目的是在具有类层次结构本身的参数的泛型类上强加类型安全层次结构.

KFunction1具有被定义为通用参数<in P1, out R>,P1in改性剂和Rout改性剂.这意味着将会:

  • P1in修饰语引入的逆变性.

    任何KFunction1<PSuper, R>将是KFunction1<P, R>if 的子类型的子PSuper类型P.但是会增加限制,P1只能作为(传入)KFunction1成员的参数出现.

  • Rout修饰符引入的协方差.

    任何KFunction1<P, RSub>将是KFunction1<P, R>if RSub的子类型的子类型R.这里R将是有限的:它只能用作成员的返回值(传递出去)KFunction1.

因此,您将能够分配KFunction1<PSuper, RSub>给类型的变量KFunction1<P, R>.

这是有意义的KFunction1,因为任何接收类型参数的函数也PSuper可以接收实例P(但反之亦然),并且RSub同时返回实例的任何函数都返回实例R(但反之亦然).


您只需撰写一个显示此行为的示例:

class Invariant<T>  {
    fun f(i: Int): T { throw Exception() } // OK
    fun f(t: T): Int { throw Exception() } // OK
}

class Contravariant<in T> {
    fun f(i: Int): T { throw Exception() } // error, T cannot be returned
    fun f(t: T): Int { throw Exception() } // OK, T is parameter type
}

class Covariant<out T> {
    fun f(i: Int): T { throw Exception() } // OK, T is returned
    fun f(t: T): Int { throw Exception() } // error, T cannnot be parameter type
}

open class Base
class Derived: Base()

val i1: Invariant<Base> = Invariant<Derived>() // error
val i2: Invariant<Derived> = Invariant<Base>() // error

val n1: Contravariant<Base> = Contravariant<Derived>() // error
val n2: Contravariant<Derived> = Contravariant<Base>() // OK

val v1: Covariant<Base> = Covariant<Derived>() // OK
val v2: Covariant<Derived> = Covariant<Base>() // error
Run Code Online (Sandbox Code Playgroud)