Kotlin学习笔记八

  • 代理数据类型
    • 枚举类
    • 密封类
  • 接口
  • 抽象类
  • 定义泛型类
  • 泛型函数
  • out关键字
  • in关键字
  • reified

代理数据类型

代理数据类型:可以用来表示一组子类型闭集。枚举类(相似对象的集合)就是一种简单的ADT。

枚举类

前面博客有介绍

enum class Card {
ACARD,
BCARD,
CCARD;
}class Driver(var card:Card){
fun checkCard():String{return when(card){Card.ACARD->"A card“Card.BCARD->"B card“.......”
}
}
}

when可以自动检测枚举类的分支,如果写漏了,会报错提示。

编译器知道完整的一套可能的子类,这将让你做详尽的表达对所有可能的子类型,而不需要一个else子句(如果你将来添加另一个子类,忘记更新时,编译器将会让你知道)。

密封类

过于复杂的ADT,使用kotlin的密封类 sealed class,以便实现复杂的定义。
密封类是一个类似于枚举类的ADT,但可以更灵活的控制某个子类型
密封类可以有若干个子类需要继承密封类子类和密封类必须定义在同一个文件。

eg

sealed class Player{class Play(val url: String, val position: Long = 0): Player()class Seek(val position: Long): Player()object Pause: Player()object Resume: Player()object Stop: Player()
}

(1)每个子类都继承基类
(2)相较于枚举类,他的子类可以更灵活。
(3)对于没有状态的子类,例如例子中 Resuem,Stop,就可以用object修饰,生成一个单例,可以看成是一种资源的节约。否则每次引用,都会创建实例,浪费
(4)其他编译器提示特性,和枚举类一样。这样看似麻烦,但是会减少bug的产生。

接口

Kotlin规定所有的接口属性和实现都要使用override关键字,接口中定义的函数,默认是open的,不需要加open关键字修饰。普通类继承,需重载的方法,需要使用open关键字修饰。

eg

interface Mode{
var name:String
val age:String
get()=xxxfun getName(){}
}class GetMode(var id:String,override name:String:Int="daxing"):Model{
override var age:String
get()=super.age//如果不覆盖
//set(value){}override fun getName()
{}}

总而言之,方法和属性,都要override关键字修饰。
接口里,还可以为属性提供getter方法,对于继承该接口类,可以选择覆盖或者不覆盖(super)。接口方法默认是public abstract

大多数情况下,接口只提供功能(函数),不会去定义属性。如果需要定义属性,一般使用抽象类

注意:
java中,jdk1.8中,接口中的变量默认是public static final,方法默认是 public abstract,除非是static方法或者默认方法。java,接口中是不存在变量的。kotlin可以有变量,但其实现,需要添加override关键字修饰。

抽象类

kotlin的抽象类和java的差不多。
抽象类其实也是一个父类,可以有自己的数据成员非抽象方法抽象方法构造方法(只是一般不能直接实例化,供子类super调用)。非抽象的子类必须实现抽象父类的抽象方法,所以抽象方法不能是private,这样子类无法实现。

java一般说 单继承,多实现。防止成员冲突。kotlin的类实现接口的属性,必须override,也是防止了成员冲突。

总而言之,接口和抽象类,就是 like a 和 is a的关系。

抽象类与接口的区别

https://blog.csdn.net/xiaoxu9522/article/details/90748914

定义泛型类

泛型类其实我们用的也比较多,例如List。
用T只是习惯,用其他字母也行。
我们自己写的泛型类,比较多的用于网络请求时的信息处理。
主要用于使用场景: 需要对不同类型的对象进行统一的处理
eg

//配合retrofit和Gson,就可以得到网络请求对象,
//不同的网络请求,保证数据结构相似,就可以用泛型类统一进行第一层处理
data class  newWorkData<T>(data:T,code:Int,msg:String)

泛型函数

eg

这里顺便复习一下takeif的用法。先决条件函数

//传入T类型,返回R类型
class Box<T>(item:T){
val  body:T = item
fun<R> getR(changeBoy:(T)->R):R?{
retun changeBoy(body).takeif(body.isNotNull())
}
}class boy(val name:String,var age:Int)
class man(val name:String,var age:int,var job:String)//使用
//这里利用匿名函数  changeBoy:(T)->R作为参数,匿名函数返回R,
//就是我们的Man,然后 getR函数根据body是否存在,返回匿名函数返回的Man
//这里就是通过匿名函数,把操作交给外部实现
val box=Box(boy("daxiong",15)
val man=box.getR{it->
Man(it.name,it.age,"hhh")
}

泛型方法既可以存在于泛型类中,也可以存在于普通的类中。如果使用泛型方法可以解决问题,那么应该尽量使用泛型方法。

注意:

定义泛型方法时,必须在返回值前边加一个< T>,来声明这是一个泛型方法,持有一个泛型T,然后才可以用泛型T作为方法的返回值。
 
泛型方法,可以限制某个类必须继承某个类才能使用如
java < T extends X> ,kotlin <T:X>
如果T不是继承X就不能当作返回值.

泛型约束

class boy(val name:String,var age:Int)
class man(val name:String,var age:int,var job:String)//T只能是man的子类
class  <T:man>

可变参数 vararg
可变参数,在java里是 … 。可变参数也存在广泛的使用场景,需要知道,
和数组参数相比,个人感觉可变参数更好用,因为可变参数是兼容数组参数的,但反之不兼容。详情见下方推荐博客。
eg

print(String... args){...
}

kotlin里,可变参数是vararg关键字
eg

print(vararg args){...
}

可变参数与泛型结合

class Box<T>(vararg item:T){
val  body:Array<out T> = item}

out关键字需要存在。后面博客会解释含义。

结合之前的可变参数,可以复习一下运算符重载
我们的类可以用[]来取值,其实就是重载
[]所对应的就是get方法
eg

class Box<T>(vararg item:T){
val  body:Array<out T> = item
operator fun get(index :Int):T?=body[index]?:"0"
}//这样Box对象,就可以使用[index]来取值了

关于可变参数和数组参数博客。

https://blog.csdn.net/baidu_37107022/article/details/78033591

out关键字

子类泛型对象可以赋值给父类泛型对象,用out。
out修饰的泛型,只能被读取,不能被修改,生产者使用
例如
List

list:List=…
list里可以包含Animal及其子类

in关键字

父类泛型对象可以赋值给子类泛型对象
in修饰的泛型,只能被修改,不能被读取,消费者使用

in和out都是针对泛型的,和普通的子类赋值个父类的情况不同。

in 和out就是提高程序扩展性,因为可以实现子类泛型和父类泛型的相互传递,但是他们也有各自的限制(生产者,消费者)

out:协变、与java的上限通配符<? extends BoundType>对应
in:逆变,与java的下限通配符<? super BoundType>对应
*: 与 java的 <?>,不过java的是<? extends Object>,kotlin的是

https://blog.csdn.net/loveblueldr/article/details/104760610?utm_medium=distribute.pc_relevant.none-task-blog-2defaultbaidujs_title~default-9.pc_relevant_antiscan&spm=1001.2101.3001.4242.6&utm_relevant_index=12

reified

配合inline使用 在运行时,确认泛型类型。java不可以在运行时知道泛型对象的类型,但kotlin可以。java一般听过反射 a.javaClass.name=="xxx"来判断,或者方法中多一个标志类类型的参数 class type

inline fun <reified T> println(any: Any) {if (any is T) {println(item)}
}

泛型擦除:
JVM并不知道泛型的存在,因为泛型在编译阶段就已经被处理成普通的类和方法;

处理机制是通过类型擦除,擦除规则:

若泛型类型没有指定具体类型,用Object作为原始类型;
若有限定类型< T exnteds XClass >,使用XClass作为原始类型;
若有多个限定< T exnteds XClass1 & XClass2 >,使用第一个边界类型XClass1作为原始类型

注意:泛型的推断,类定义的泛型和方法定义的泛型不是同一个,二者没有任何关系.


class<T> A{
fun get(val getA:()->T):T{
//z这里的泛型T和类定义的泛型没有任何关系,是由匿名函数 getA决定的
return geta()
}
}

Kotlin学习笔记八-数据代理类型,接口与抽象类相关推荐

  1. Kotlin学习笔记12——数据类和密封类

    Kotlin学习笔记12--数据类和密封类 前言 数据类 在类体中声明的属性 复制 componentN 解构声明 密封类 尾巴 前言 上一篇,我们学习了Kotlin中的拓展,今天继续来学习Kotli ...

  2. Kotlin学习笔记(3)- 语法

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

  3. Kotlin学习笔记(2)- 空安全

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

  4. Kotlin学习笔记(1)- 环境配置

    系列文章全部为本人的学习笔记,若有任何不妥之处,随时欢迎拍砖指正.如果你觉得我的文章对你有用,欢迎关注我,我们一起学习进步!kotlin学习笔记系列首发简书和CSDN Kotlin学习笔记(1)- 环 ...

  5. Kotlin 学习笔记(八)—— Kotlin类与对象之接口

    Kotlin 学习笔记(八)-- Kotlin类与对象之接口 Kotlin学习笔记系列教程 Kotlin 学习笔记(一)-- 概述.学习曲线.开发工具.参考资料 Kotlin 学习笔记(二)-- 基础 ...

  6. ZooKeeper学习笔记(八):ZooKeeper集群写数据原理

    写数据原理 写流程直接请求发送给Leader节点 这里假设集群中有三个zookeeper服务端 ACK (Acknowledge character)即是确认字符,在数据通信中,接收站发给发送站的一种 ...

  7. Kotlin学习笔记19 阶段复习1

    参考链接 示例来自bilibili Kotlin语言深入解析 张龙老师的视频 基础部分 Kotlin学习笔记 第一章开始 第二章 基础_积跬步 至千里-CSDN博客 类与继承 Kotlin学习笔记 第 ...

  8. Kotlin 学习笔记(四)—— 协程的基础知识,面试官的最爱了~

    又是一个月没见了,坚持永远是世上最难的事情,但,往往难事才会有更大的收获.与君共勉~ 前段时间一直在学习 Compose,所以导致 Kotlin 笔记系列搁置了好久.一方面是因为 Compose 的学 ...

  9. 《Go语言圣经》学习笔记 第七章 接口

    <Go语言圣经>学习笔记 第七章 接口 目录 接口是合约 接口类型 实现接口的条件 flag.Value接口 接口值 sort.Interface接口 http.Handle接口 erro ...

  10. Kotlin学习笔记--Kotlin之集合

    Kotlin学习笔记--Kotlin之集合 集合类 1. List 集合 1.1 不可变list 1.2 可变list MutableList 1.3 集合遍历 1.4 List的操作函数 1.5 l ...

最新文章

  1. 机器学习-Andrew Ng课程笔记
  2. EfficientNetv2测试
  3. [导入]sqlserver2005 数据挖掘控件研究
  4. VS2008中配置 Windows SDK v7
  5. 如何在Angular项目里创建新的Service
  6. Kubernetes(十七) 基于NFS的动态存储申请
  7. 李洪强iOS开发Swift篇—02_变量和常量
  8. matlab第十章实验,matlab 图像函数以及运用(第十章)
  9. springboot 关于第三方包 打包问题
  10. aws s3 静态网站_使用AWS S3存储桶启动静态网站
  11. html range 样式,美化 input range 控制条
  12. IOS 蓝牙开发(一)蓝牙协议基础知识
  13. PHP探测手机客户端
  14. 关于约束多目标MOEA/D-DAE
  15. matlab:读取图像序列
  16. Windows照片查看器
  17. 德国《世界报》:在上海车牌与小汽车一样贵
  18. Android—传感器-距离传感器(ProximitySensor)
  19. scikit-learn中的PCA
  20. 干货分享:Google搜索如何限制在具体的一个州或城市

热门文章

  1. linux+tar怎样解压zip文件内容,linux tar压缩解压文件
  2. 《游戏系统设计四》游戏资源系统太复杂? 啥?你不会?一步一步带你分析并实现,源码直接拿走
  3. 邮箱163登录入口,邮箱163如何注册?
  4. NVIDIA Riva中文手册 (五) —— Riva TTS语音合成API的使用
  5. 第七十五章 SQL命令 START TRANSACTION
  6. 栅格数据中的 Zone 与 Region
  7. Bootstrap注册页面模板
  8. html 怎么让他变成圆角,html让图片变圆角
  9. Python numpy函数:shape用法
  10. 迅雷 linux 命令行 版本号,linux下完美运行迅雷5.8.9.662