接口、抽象类、泛型,这些在Java中我们都是常见且经常使用的,相信大家都不会陌生了。这里我们就看下它们的异同吧。
一 接口
Kotlin规定所有的接口属性和函数实现都要使用override关键字,接口中定义的函数并不需要open关键字修饰,他们默认就是open的。
1.1 接口的定义及实现
interface Movable{
val maxSpeed:Int
var wheels:Int
fun move(movable: Movable):String
class Car(_name:String,override var wheels:Int = 4):Movable{
var name = _name
override val maxSpeed: Int
get() = 100
override fun move(movable: Movable): String {
return "$name max speed is ${movable.maxSpeed},has ${movable.wheels} wheels"
val car = Car("BMW",8)
println(car.move(car))
BMW max speed is 100,has 8 wheels
1.2 接口默认实现
interface Movable{
val maxSpeed:Int
get() = (1..500).shuffled().last()
var wheels:Int
fun move(movable:Movable):String
class Car(var name:String,override var wheels:Int = 4):Movable{
override val maxSpeed: Int
get() = super.maxSpeed
override fun move(movable: Movable): String {
return "$name has $wheels wheel,max speed is ${movable.maxSpeed}"
这里的默认实现只是在接口里默认实现了属性取值,然后实现类可以直接取父接口的属性值。总体来看Kotlin的接口使用与Java差异不太大。
二 抽象类
要定义一个抽象类,你需要在定义之前加上abstract关键字,除了具体的函数实现,抽象类也可以包含抽象函数(只定义不实现)。
2.1 抽象类定义及实现
abstract class Gun(val range:Int){
abstract fun trigger():String
class AK47(val price:Int,range:Int):Gun(range = range){
override fun trigger(): String {
return "AK47 price is $price,shooting $range"
val aK47 = AK47(9999,108)
println(aK47.trigger())
AK47 price is 9999,shooting 108
感觉没什么好多解释的了,除了一些写法不一样,其余与Java基本一致,看代码理解下就可以了。
三 泛型
泛型通常用字母T(Type)表示,要是想用其它字母甚至是英文单词都是可以的。不过在其它支持泛型的语言通常都使用T,慢慢的成了一个约定俗成。为了让别人更容易理解你的代码,也建议使用T。
3.1 定义泛型类
泛型类的构造函数可以接受任何类型
class MagicBox<T>(item:T){
var subject:T = item
data class Boy(val name:String,val age:Int)
data class Dog(val weight:Int)
val box0 = MagicBox(Boy("Jack",18))
val box1 = MagicBox(Dog(20))
3.2 泛型函数
在上面例子的基础上我们将磨合改一改
class MagicBox1<T>(item:T){
var availavle = true
private var subject:T = item
fun fetch():T?{
return subject.takeIf { availavle }
val box0 = MagicBox1(Boy("Jack",18)).fetch()
val box1 = MagicBox1(Dog(20)).fetch()
println(box0.toString())
println(box1.toString())
Boy(name=Jack, age=18)
Dog(weight=20)
嘿嘿,是不是感觉很奇怪,明明直接实例化就好了,还搞得那么麻烦。其实这样写也是有其好处的,可以方便统一实例化工作的管理,在Android源码里就使用了很多这样的构建方式,也是一种构建思想了。当然,它是用Java写的而已。
3.3 多泛型参数
泛型函数或泛型类也可以有多个泛型参数。感觉很绕,无法理解。那么我们通俗点,比如我们开始传入的是一个男孩,然后最后我们需要得到一个男人怎么处理?这个要是你玩过RxJava的话,应该是处理过类似的需求的。
class MagicBox2<T>(item:T){
var availavle = true
private var subject:T = item
fun fetch():T?{
return subject.takeIf { availavle }
fun <R>fetch(subjectModFunction:(T)->R):R?{
return subjectModFunction(subject).takeIf { availavle }
data class Man(val name:String,val age:Int)
val box2 = MagicBox2(Boy("Jack",18)).fetch{
Man(it.name,it.age.plus(10))
println(box2.toString())
Man(name=Jack, age=28)
在变换的过程中一定有函数的介入处理的,但事先我们并不知道它的具体类型,所以有了T、R两个泛型,然后通过外部传入lambda表达式来进行了转换。这种处理方式在实际项目中是会经常用到的。
3.4 泛型约束
如果要确保我们的泛型只能是某种类型的泛型该怎么处理呢?那么我们需要对我们的泛型进行条件约束。
class MagicBox3<T:Man>(item:T){
var availavle = true
private var subject:T = item
fun fetch():T?{
return subject.takeIf { availavle }
val box4 = MagicBox3(Man("Jack",18))
其实类似的用法我们在Java中也应该写过,就是对泛型进行约束,要求只能是某种类型的子类。Java的写法是 T extend Man 这种写法而已。
3.5 可变参数泛型
我们设计的程序一次只能放入一个,但如果我一次想放入N个,但又可能不确定,那这时候我们的可变参数就派上用场了。可变参数使用vararg关键字。
class MagicBox4<T>(vararg item:T){
var availavle = true
private var subject:Array<out T> = item
fun fetch(index:Int):T?{
return subject[index].takeIf { availavle }
val box5 = MagicBox4(Boy("Jack",18),Dog(20),Man("Jacky",30))
println(box5.fetch(1))
Dog(weight=20)
这里需要注意的点:1、需要使用vararg关键字指明参数为可变参数 2、subject接收的类型变为了Array,且类型需要使用out进行修饰(out in在下节在说) 3、取值的时候需要下标做取值索引
3.6 []取值操作符
在上面的代码中,如果我们想通过box5[1]这种方式进行取值是行不通的。但我们可以通过重载运算符函数get来实现此功能。
class MagicBox4<T>(vararg item:T){
var availavle = true
private var subject:Array<out T> = item
fun fetch(index:Int):T?{
return subject[index].takeIf { availavle }
operator fun get(index: Int):T? = subject[index].takeIf { availavle }
通过重载get运算符函数,我们就可以通过[]直接取值了。
接口、抽象类、泛型,这些在Java中我们都是常见且经常使用的,相信大家都不会陌生了。这里我们就看下它们的异同吧。一 接口Kotlin规定所有的接口属性和函数实现都要使用override关键字,接口中定义的函数并不需要open关键字修饰,他们默认就是open的。1.1 接口的定义及实现interface Movable{ val maxSpeed:Int var wheels:Int fun move(movable: Movable):String}class Car(_
2、将运行期的类型转换异常提前到了编译期,保证类型的安全,避免类型转换异常
3、怎么去定义和使用泛型?
我们可以给一个类,方法,或者接口指定泛型,在具体使用的地方指定具体的类型
一、Java 泛型
要学习好 Kotlin 泛型,我们先要对 Java 泛型足够的了解,因为 Kotlin 泛型和 Java 泛型基本上是一样的,只不过在 Kotlin 上有些东西换了新的写法
1、泛型的简单使用
在 Java 中,我们可以给一个类,方法,或者接口指定泛型,在具体使用的地方指定具体的类型
1)、定义一个泛型类,在类名
Kotlin 抽象与接口
其实在 Kotlin 中继承、接口大部分和 Java 是一样的,但是在语法层面支持是不一样。因为 Kotlin 会有一层语法糖可以很方便高效地声明某个语法,从而让你把更多精力专注在业务逻辑上,而不是语法代码模板上。然后我们还会一起来聊下 Kotlin 多继承的实现,Kotlin 和 Java 一样都是单继承,这一点是毋庸置疑的,但是我们也会需要多继承场景,那么 Kotlin 是怎么解决这样场景的呢?大家肯定想到的是接口多继承,具体怎么一起来看看吧。
1. 抽象与接口
继承、接口继承子类有主构造函数子类没有主构造函数子类重写父类的方法属性重写接口实现接口接口中的属性接口继承解决覆盖冲突
在 Kotlin 中所有类都有一个共同的超类 Any,这对于没有超类型声明的类是默认超类:
class Ex...
omyrobin:
Android之Hook AMS实现集中登录管理
omyrobin:
Kotlin中使Companion object不被混淆
无脸妖男:
一起学Kotlin(9)_扩展函数
大家一起学编程(python):