X

Kotlin代数数据类型、模式匹配、泛型相关(学习笔记三)

三、代数数据类型和模式匹配

其实都是些设计思想,我们在开发中都用到了,需要在开发中不断积累领悟。

1、代数数据类型概念理解

代数就是能代表数字的字母或符号
这种用代数或者数字转换成的类型,以及通过这些类型所产生的的新的类型就叫做代数数据类型,有点绕口哈哈。
其实我们用的枚举就是代数数据类型的一种,后边我们会慢慢体会到它带来的好处。

2、何为模式?模式即为表达式,常见模式有常量模式、类型模式、逻辑表达式模式

常量模式就是比较两个常量是否相等,比如if else 、switch case
类型模式类似于java的 instanceOf  circle instanceOf  Shape     kotlin的 is Shape 类型检查
逻辑表达式模式可以理解为 if else 、switch case实现起来比较麻烦(比如在if条件里做比较多的逻辑判断等),用逻辑表达式模式实现起来比较简洁的模式,

3、何为模式匹配?模式匹配中的模式即为表达式,匹配的也是表达式,模式匹配的核心就是解构(反向构造表达式),如下结构:

when(expre){
    expre1->{}
    expre2->{}
}

四、类型系统

1、java NPE(空指针)

 解决方案:

抛异常处理
采用注解@NotNull  @Nullable
用Optional对象对可空的数据进行装箱,这类Optional对象必须拆箱后才能参与运算,因而拆箱的步骤就提醒使用者必须处理null的情况。但是这种情况在大数据量的情况下会导致损耗性能和时间的增加

2、kotlin的可空类型

安全调用:a?.b?.c 只有a或者b不为空的情况下才会继续往下调用
Elvis操作符(合并运算符):java写法 string a = b==null?c:b.e; kotlin大法 var a = b?c:.e
非空断言:!!  a!!.b 当a为空时就会抛出NPE
智能类型转换,因为kolin是会进行类型自动推导的,所以他没有java的强转,为了语义或者阅读方便我们一般用 as或者as?来标记变量的类型,as?会防止变量为空触发空引用。
类型转换的封装 inline fun <reified T> cast(original: Any) : T? = original as? T
使用 var a = cast<String>

3、面向对象设计

  1. Any是所有非空类型的超类,Any?是所有类型的超类 Any相当于java的 Object

  2. 自动装箱,基本类型转为包装类,自动拆箱是包装类转为基本类型

  3. Kotlin中一切皆对象,Int等价于java的int Int?等价于java的Integer

  4. 新数组 Array 、IntArray(int[])、CharArray(char[])、ShortArray(short[])

  5. val a = arrayOf(1,2,3); 
     val a = intArrayOf(1,2,3); 
     IntArray 并不是Array的子类
    

4、泛型

   1、 泛型类 class Animal<T> {} 

 2、泛型接口 interface IAnimal<T> {}  

 3、泛型方法 fun <T> initAnimal(param: T) {}

   4、泛型约束, 表示我们可以指定泛型类型(T)的上界,即父类型,默认的上界为Any?,如果只有一个上界可以这样指定:

fun <T : Animal<T>> initAnimal(param: T) {}

即Animal<T>就是上界类型,这里使用了:,在 Java 中对应extends关键字,如果需要指定多个上界类型,就需要使用where语句:

fun <T> initAnimal(param: T) where T : Animal<T>, T : IAnimal<T> {}

   5、协变和逆变

Kotlin 中的泛型是默认不型变的
in代表泛型参数类型逆变,逆变泛型类型的父类型是被保留的,它只能出现在函数的输入位置,作为参数。
out代表泛型参数类型协变,协变泛型类型的子类型是被保留的。
消费者 in, 生产者 out,统称为型变。
使用 out 使得一个类型参数协变,协变类型参数只能用作输出,可以作为返回值类型但是无法作为入参的类型,而in则刚好相反。
比较:
Kotlin 中的out A类似于 Java 中的? extends A,即泛型参数类型必须是A或者A的子类,用来确定类型的上限
Kotlin 中的in A类似于 Java 中的? super A,即泛型参数类型必须是B或者B的父类,用来确定类型的下限

 6、于星号投射,其实就是*代指了所有类型,相当于Any?我们不知道泛型参数的类型信息时,但仍需要安全的使用它时,可以使用星投影,用星号*表示,星投影和 Java 中的原始类型很像,但星投影是安全

示例:

class A<T>(val t: T, val t2 : T, val t3 : T)
class Apple(var name : String)
fun main(args: Array<String>) {
    //使用类    
    val a1: A<*> = A(12, "String", Apple("苹果"))
    val a2: A<Any?> = A(12, "String", Apple("苹果"))   //和a1是一样的
    val apple = a1.t3    //参数类型为Any
    println(apple)
    val apple2 = apple as Apple   //强转成Apple类
    println(apple2.name)
    //使用数组
    val l:ArrayList<*> = arrayListOf("String",1,1.2f,Apple("苹果"))
    for (item in l){
        println(item)
    }
}

更多学习

kotlin基础语法(学习笔记一)
kotlin面向对象(学习笔记二)

关注我获取更多知识或者投稿

本网站文章均为原创内容,并可随意转载,但请标明本文链接
如有任何疑问可在文章底部留言。为了防止恶意评论,本博客现已开启留言审核功能。但是博主会在后台第一时间看到您的留言,并会在第一时间对您的留言进行回复!欢迎交流!
本文链接: https://leetcode.jp/kotlin代数数据类型、模式匹配、泛型相关(学习笔记äb/
Categories: Android
admin: