kotlin内联函数_Kotlin简化-协方差,协方差和内联函数

kotlin内联函数

Kotlin has gained considerable popularity in the past few years. The cross-platform nature and interoperability with Java & JVM have increased the adaptability & acceptance from the developer community. Moreover, Kotlin first approach by Google attracted Android developers to adapt it.

在过去的几年中,Kotlin受到了极大的欢迎。 Java和JVM的跨平台性质和互操作性提高了开发人员社区的适应性和接受度。 此外,谷歌的Kotlin第一种方法吸引了Android开发人员对其进行调整。

I am intending to create a series of simplified Kotlin concepts which helped me to gain some hand over Kotlin:

我打算创建一系列简化的Kotlin概念,这些概念有助于我掌握Kotlin:

协方差和协方差 (The Covariance & Contravariance)

Similar to Java, Kotlin also supports generics which enables us to operate on a method or object without providing actual type at compile time along with type safety.

与Java类似,Kotlin还支持泛型,这使我们能够在方法或对象上进行操作而无需在编译时提供实际类型以及类型安全。

Kotlin takes it one step further by providing out (covariance) & in (contravariance).

Kotlin通过提供out (协方差)和in (协方差)进一步向前迈进了一步。

Under the hood it’s as simple as below:

内幕如下所示:

Imagine there are two classes, A is parent/super class & B is child/sub class

假设有两个班级, A是父母/超级班级, B是孩子/子班级

open class A {
//some methods & member variable
}class B : A() {
// some mehods & member variables
}

协方差: (Covariance:)

It means that you can use a subtype in place of a supertype.

这意味着您可以使用子类型代替超类型。

Let’s take an example:

让我们举个例子:

class GenericClass<T: A>{
// some actions to be done for GenericClass
}

Now if you try to do something like:

现在,如果您尝试执行以下操作:

val genericClass:GenericClass<A> = GenericClass<B>()

you will get a compilation error TypeMismatch

您将收到编译错误TypeMismatch

Now if we change:

现在,如果我们更改:

class GenericClass<out T: A>{
// some actions to be done for GenericClass
}

The statement will compile successfully.

该语句将成功编译。

Some rules for Covariance When a class or interface generic type is prefixed with out:

协方差的一些规则当类或接口泛型类型以out为前缀out

  • It can be only be used in an “out” position, such as a function return type.

    它只能在“输出”位置使用,例如函数返回类型。
  • It can be also used as val property

    也可以用作val属性

  • It cannot be used as var property or function input

    不能用作var属性或函数输入

All the collection interface in Kotlin have a generic type defined with out .

Kotlin中的所有collection接口都具有使用out定义的通用类型。

矛盾: (Contravariance:)

It means that you can use supertype in place of a subtype

这意味着您可以使用超型代替子型

Let’s take an example:

让我们举个例子:

class GenericClass<T: A>{
// some actions to be done for GenericClass
}

Now if you try to do something like:

现在,如果您尝试执行以下操作:

val genericClass:GenericClass<B> = GenericClass<A>()

you will get a compilation error TypeMismatch

您将收到编译错误TypeMismatch

Now if we change

现在,如果我们改变

class GenericClass<in T: A>{
// some actions to be done for GenericClass
}

The statement will compile successfully.

该语句将成功编译。

Some rules for Contravariance When a class or interface generic type is prefixed with in :

协方差的一些规则当类或接口泛型类型以in为前缀时:

  • It can only be used in an “in” position such as function input type

    只能在“输入”位置使用,例如功能输入类型
  • It cannot be used as “out” position i.e. cannot be used as val or var property

    它不能用作“出”位置,即不能用作valvar属性

inline函数 (inline function)

Kotlin provides high flexibility & reusability through higher-order functions which takes a lambda as the input parameter. However, this comes with a slight penalty in terms of performance. When you declare a lambda, it's treated as a normal object in Java. This means, it will have its memory allocated for all the variables used within the lambda and so on.

Kotlin通过使用lambda作为输入参数的高阶函数提供了高度的灵活性和可重用性。 但是,这会在性能方面带来一些损失。 声明lambda时,它将被视为Java中的普通对象。 这意味着,它将为lambda等中使用的所有变量分配其内存。

e.g. We declare a high order function as follows:

例如,我们声明一个高阶函数,如下所示:

fun printSalutation(message: (String) -> String) {
println(message("MR"))
}

Then you invoke the function:

然后调用该函数:

fun test() {
printSalutation { "Hello $it Foo. How are you?" }
}

It will be represented as follows in Kotlin byte code:

它将以Kotlin字节码表示如下:

public final void printSalutation(@NotNull Function1 message) {
Intrinsics.checkParameterIsNotNull(message, "message");
Object var2 = message.invoke("MR");
boolean var3 = false;
System.out.println(var2);
}public final void test() {
this.printSalutation((Function1)null.INSTANCE);
}

If you notice, it creates an extra instance and passes it to printSalutation .

如果您注意到,它将创建一个额外的实例,并将其传递给printSalutation

You can generate this using Android Studio as follows:

您可以使用Android Studio生成此文件,如下所示:

Tools → Kotlin → Show kotlin byte code → Decompile 
Image for post

Then from the window in right select Decompile

然后从右侧的窗口中选择Decompile

Image for post

You can easily mitigate this overhead by using inline function which removes the need to use an object instance and perform variable memory allocations for the lambda. It is as simple as prefixing inline keyword to the function as follows:

您可以通过使用inline函数轻松减轻这种开销,该函数无需使用对象实例并为lambda执行可变的内存分配。 只需将inline关键字添加到函数即可,如下所示:

inline fun printSalutation(message: (String) -> String) {
println(message("MR"))
}

This time when you decompile the code:

这次,当您反编译代码时:

public final void printSalutation(@NotNull Function1 message) {
int $i$f$printSalutation = 0;
Intrinsics.checkParameterIsNotNull(message, "message");
Object var3 = message.invoke("MR");
boolean var4 = false;
System.out.println(var3);
}public final void test() {
int $i$f$printSalutation = false;
String it = "MR";
int var4 = false;
it = "Hello " + it + " Foo. How are you?";
var4 = false;
System.out.println(it);
}

As you notice when you prefix a function with inline the generated code removes the call and replaces it with the contents of lambda function thereby removing the overhead and make the code run faster.

正如您注意到的那样,当您使用inline函数为函数添加前缀时,生成的代码将删除该调用,并将其替换为lambda函数的内容,从而消除了开销,并使代码运行更快。

总结 (Summaries)

  • Covariance: Use a subtype in place of a supertype.

    协方差:使用子类型代替超类型。

  • Contravariance: Use supertype in place of a subtype

    矛盾:使用超型代替子型

  • inline function: Improve the performance impact caused by higher-order function.

    内联函数:改善由高阶函数引起的性能影响。

下一步: (Coming Next:)

Kotlin Streams, The Elvis ?: operator, Extension functions, copy with data class, Nothing vs Unit, sealed class vs enum

Kotlin Streams,Elvis?:运算符,扩展功能,使用数据类进行复制,Nothing vs Unit,密封类vs枚举

翻译自: https://medium.com/swlh/kotlin-simplified-covariance-contravariance-inline-function-2a1fb55dbb74

kotlin内联函数

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值