kotlin泛型_Kotlin泛型

kotlin泛型

In this tutorial, we’ll be looking in Kotlin Generics and Variances.

在本教程中,我们将研究Kotlin的泛型和变异性。

泛型 (Generics)

Generics are a powerful feature that allows us to define a common class/method/property that can be operated using different types while keeping a check of the compile-time type safety.
They are commonly used in Collections.
A generic type is a class or interface that is parameterized over types. We use angle brackets (<>) to specify the type parameter. To understand Generics, we need to understand types.
Every class has a type which is generally the same as the class.
Though, in Kotlin a nullable type such as String? won’t be considered a class type.
Same goes for a List<String> etc.

泛型是一项强大的功能,它使我们能够定义可以使用不同类型进行操作的通用类/方法/属性,同时保持对编译时类型安全性的检查。
它们通常用于集合中。
泛型类型是通过类型进行参数化的类或接口。 我们使用尖括号(<>)来指定type参数。 要了解泛型,我们需要了解类型。
每个类的类型通常与该类相同。
但是,在Kotlin中,可否为null的类型(例如String)? 不会被视为类类型。
List <String>等也是如此。

An example of Kotlin Generic classes is given below:

以下是Kotlin泛型类的示例:

fun main(args: Array<String>) {
    var a = A("")
    var b: A<Int> = A(1) //explicit
}

class A<T>(argument: T) {
    var result = argument
}

We’ve instantiated the class using explicit types as well as allowing the compiler to infer them.

我们使用显式类型实例化该类,并允许编译器推断它们。

方差 (Variance)

Variance is all about substituting a type with subtypes or supertypes.
The following thing works in Java:

方差就是将类型替换为子类型或超类型。
以下内容在Java中起作用:

Number[] n = newNumber[2];
n[0] = newInteger(1);
n[1] = newDouble(47.24);

This means Arrays in Java are covariant.

这意味着Java中的数组是协变的


Subtypes are acceptable.
可以接受子类型。
Supertypes are not.
超类型不是。

So using the covariant principle the following Java code works as well:

因此,使用协变原理,以下Java代码也可以正常工作:

Integer[] integerArray = {1,2,3};
Number[] numberArray = integerArray;

The Number class is the parent of Integer class hence the inheritance and subtyping principle works above.
But the above assignment is risky if we do something like this:

Number类是Integer类的父级,因此继承和子类型化原则适用于上面。
但是,如果我们做这样的事情,上面的分配是有风险的:

numberArray[1] = 4.56 //compiles successfully

This would lead to a runtime exception in Java since we cannot store a Double as an Int.

因为我们不能将Double存储为Int,这将导致Java中的运行时异常。

Kotlin Arrays stays away from this principle by making arrays invariant by default.

Kotlin数组通过默认使数组不变而背离了这一原理。


Subtypes are not allowed.
不允许使用子类型。
Supertypes are not allowed.
不允许超类型。

So the above runtime error won’t occur with Kotlin Arrays.

因此,使用Kotlin阵列不会发生上述运行时错误。

val i = arrayOf(1, 2, 3)
val j: Array<Any> = i //this won't compile.

Hence, one of the major differences in variances between Kotlin and Java is:

因此,Kotlin和Java之间的主要差异之一是:

Kotlin Arrays are invariant. Java Arrays are covariant.
Kotlin数组是不变的。 Java数组是协变的。

Applying the above concepts DON’T COMPILE when used with Generics and Collections for both Java and Kotlin.

当将上述概念与Java和Kotlin的泛型和集合一起使用时,请不要编译。

import java.util.ArrayList;
import java.util.List;

public class Hi {

    public static void main(String[] args) {
        List<String> stringList= new ArrayList<>();
        List<Object> myObjects = stringList; //compiler error
    }

}

By default, the Generic types are invariant. In Java, we use wildcard characters to use the different type of variances.
There are two major types of variances besides invariant.

默认情况下,泛型类型为invariant 。 在Java中,我们使用通配符来使用不同类型的方差。
除了不变以外,还有两种主要的方差类型。

  • Covariant

    协变
  • Contravariant

    逆变的

协变 (Covariant)

A ? extends Object is a wildcard argument which makes the type as covariant.
Our previous java code now works fine.

一个? extends Object ? extends Object是一个通配符参数,它使类型成为协变
我们之前的Java代码现在可以正常工作。

public class Hi<T> {


    public static void main(String[] args) {


        Hi<Integer> j = new Hi();
        Hi<Object> n = j; //compiler error
        Hi<? extends Object> k = j; //this works fine

    }

}

The third statement is an example of Covariance using wild card arguments.

第三条语句是使用通配符参数的协方差示例。

The modifier out is used for applying covariance in Kotlin.

修改器out用于在Kotlin中应用协方差。

fun main(args: Array<String>) {


    val x: A<Any> = A<Int>() // Error: Type mismatch
    val y: A<out Any> = A<String>() // Works
    val z: A<out String> = A<Any>() // Error
}
class A<T>

In Kotlin, we can directly annotate the wildcard argument on the parameter type of the class. This is known as declaration-site variance.

在Kotlin中,我们可以在类的参数类型上直接注释通配符参数。 这称为声明站点差异

fun main(args: Array<String>) {
    val x: A<Any> = A<Int>()
}

class A<out T>

The above Kotlin code looks more readable than the Java one.

上面的Kotlin代码看起来比Java代码更具可读性。

fun main(args: Array<String>) {
    var correct: Container<Vehicle> = Container<Car>()
    var wrong: Container<Car> = Container<Vehicle>()
}


open class Vehicle
class Car : Vehicle()
class Container<out T>

Use out
用完
Used to set substitute subtypes. Not the other way round
用于设置替代子类型。 并非相反

逆变 (Contraconvariant)

This is just the opposite of Covariance. It’s used to substitute a supertype value in the subtypes.
It cannot work the other way round.
It uses the in modifier

这与协方差正好相反。 它用于替换子类型中的超类型值。
反之亦然。
它使用in修饰符

fun main(args: Array<String>) {
    var correct: Container<Car> = Container<Vehicle>()
    var wrong: Container<Vehicle> = Container<Car>()
}

open class Vehicle

class Car : Vehicle()

class Container<in T>
in is equivalent to <? super T> of Java. in的等效于<? Java的超级T>。
Kotlin
Kotlin out is equivalent to <? extends T> of Java. out等于<? 扩展了Java的T>。

This brings an end to this tutorial on Kotlin Generics and Variance.

这结束了有关Kotlin泛型和方差的本教程。

翻译自: https://www.journaldev.com/20454/kotlin-generics

kotlin泛型

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值