[AS3.6.1]Kotlin学习笔记5(类说明,函数说明)

前言

kotlin学习第五篇文章!
历史文章
[AS3.6.1]Kotlin学习笔记1(基本声明,函数,条件)
[AS3.6.1]Kotlin学习笔记2(常量,数组,修饰符)
[AS3.6.1]Kotlin学习笔记3(简化操作,泛型)
[AS3.6.1]Kotlin学习笔记4(接口,Lambda,协程)

前面我们讲过一些类的内容,比如Any就是Object,使用:替代java中的继承extends和接口implements,多个之间使用,隔开等。现在我们来具体了解下类,包括一些说明和objectdata等。

类的说明

  1. kotlin的Any就是java的Object
  2. kotlin中类和函数一样默认都是用public final修饰的,需要继承的时候要加上open
  3. java中的继承和接口在kotlin中均用:替代,多个用,隔开
  4. 获得类class,kotlin类为KClass::class java类为JClass::class.java

我们在简化中说过 以下简化

class KClass {
    var name: String
    constructor(name: String){
        this.name = name
    }
}

//可以简化成
class KClass constructor(var name: String){
}

class KClass(var name: String){  
}

如果我需要设置一个私有的构造函数类,写法如下

class KClass private constructor(var name: String){  
}

嵌套类

java中我们也经常会写到,写法和java差不多

class KClass{
	...
	class KClass2{
		...
	}
}

	//调用
	val kClass2 = KClass.KClass2()

内部类

因为我们上面说过类都是默认使用public final修饰的,所以想要一个内部类就需要使用inner修饰

class KClass{
	...
	inner class KClass3{
		...
	}
}

	//直接调用
	//报错提示 Constructor of inner class KClass3 can be called only with receiver of containing class
	val kClass3 = KClass.KClass3()

对象类 object

这个我们之前也提过,object类就是对象类直接生成一个饿汉式的单例类。这边再次说下使用情况

那在实际使用中,在 objectcompanion objecttop-level 中该选择哪一个呢?
简单来说按照下面这两个原则判断:
如果想写工具类的功能,直接创建文件,写 top-level「顶层」函数。
如果需要继承别的类或者实现接口,就用 object 或 companion object。

数据类 data

这个我们在协程的时候使用了下,也没说明。这边就开始讲下数据类。
data类似于lombok的@Data注解,可以自动生成toString()equals()hashcode()copy()等方法。

data class KData(
    val str: String,
    val int: Int,
    val `data`: Any
)

	//使用
    val kData1 = KData("data1", 5, false)
    val kData2 = kData1.copy(str = "data2", data = "Any2")
    val (str, int, data) = kData1

    println(kData1)	//KData(str=data1, int=5, data=false)
    println(kData2)	//KData(str=data2, int=5, data=Any2)
    println("str = $str, int = $int, data = $data") //str = data1, int = 5, data = false

我们可以看到,data生成的数据类非常的好用,可以直接copy数据,并且还支持解构。

密封类 sealed

先来看下说明

密封类用来表示受限的类继承结构:当一个值为有限几种的类型, 而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合 也是受限的,但每个枚举常量只存在一个实例,而密封类 的一个子类可以有可包含状态的多个实例。
声明一个密封类,使用 sealed 修饰类,密封类可以有子类,但是所有的子类都必须要内嵌在密封类中。
sealed 不能修饰 interface , abstract class(会报 warning,但是不会出现编译错误)

sealed class House
class Apartment : House()
class Hotel : House()

	//检查方法
    private fun check(house: House) = when(house){
        is Apartment -> println("是 公寓")
        is Hotel -> println("是 酒店")
    }

	//使用
    check(Apartment())	//是 公寓
    check(Hotel())	//是 酒店

我们发现这就是高级的枚举使用,还是可以设置属性的枚举。并且我们可以看到使用when的时候不在需要设置else了因为密封类已经帮我们判断了所有的情况。

函数

我们前面说过函数相关的内容,kotlin的函数有嵌套函数扩展函数高阶函数内联函数

和类一样,kotlin的函数默认都是public final 修饰,想要能够被重构需要加入open,如果是继承父类的方法还要加上overrider

我们还知道kotlin的函数是可以设置默认值的

    fun info(id: Int, name: String = "张三", sex: String = "男"){
        println("id = $id, name = $name, sex = $sex")
    }
	
	//使用
    info(1)	//id = 1, name = 张三, sex = 男
    info(2, "李四")	//id = 2, name = 李四, sex = 男
    info(3, "王五", "女")	//id = 3, name = 王五, sex = 女

那么如果混合开发中我们需要让java也可以实现,只需要加入注释@JvmOverloads

    @JvmOverloads
    fun info(id: Int, name: String = "张三", sex: String = "男"){
        println("id = $id, name = $name, sex = $sex")
    }

这样我们就不需要为了让java可以使用写多个重载函数了。

嵌套函数(本地函数)

之前提过,这边就写下例子

	fun aFun(){
		...
		fun bFun(){
			...
		}
		bFun()
	}

扩展函数

扩展函数算是kotlin中很好用的特性,可以在不修改原来类,函数的情况直接加入新的函数或者重写函数。

比如我们为CharSequence加入一个toList函数

    fun CharSequence.toList(): List<Char>{
        val list = ArrayList<Char>()
        for (c in this) {
            list.add(c)
        }
        return list
    }

	//使用
	val chars = "abcdefg".toList()
    for (char in chars) {
        print("$char ")	//结果 a b c d e f g 
    }

高阶函数

[AS3.6.1]Kotlin学习笔记4(接口,Lambda,协程)接口中我们已经对高阶函数有了一定的理解了。这边复述一下就是可以让函数传递的变量也是函数。简单示例如下

    fun aFun(block: () -> Unit){
        block()
    }

    fun bFun(){
        println("bFun")
    }

	//使用
    aFun {
        println("aFun")	//aFun
    }

    aFun {
        bFun()	//bFun
    }

内联函数

通过 inline 修饰的函数为内联函数

看下面的例子

    fun cFun(){
        var x = 1
        dFun()
        println("cFun $x")
    }

    inline fun dFun(){
        var y = 2
        var z = 3
        println("dFun $y $z")
    }

调用cFun如果没有加inline是会增加内存和性能的开销,为什么呢?因为加入inline后实际真实的cFun代码是如下

    fun cFun(){
        var x = 1
        var y = 2
        var z = 3
        println("dFun $y $z")
        println("cFun $x")
    }

加入内联之后,编译后kotlin会自动将内联的代码直接写在cFun中,并不会有两个方法。
而且实际内联函数一般都用于lambda中,但注意的是,要内联的函数带的lambda不宜过大,否则会造成生产class文件过大,所以当内联函数太大的时候可以使用noinline取消lambda的内联。

总结

关于类和函数的补充!

资料

Kotlin入门
Kotlin基础之内联函数
Kotlin 进阶用法: 内联函数

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值