中缀表达式
- 使用中缀表达式就是想让代码更加简洁易懂
- 使用条件:必须是成员函数或扩展函数;必须只有一个参数;参数不可能是可变参数或默认参数。
class Person{
infix fun sayHelloTo(name:String){
println("你好${name}")
}
}
val stenve=Person()
stenve.sayHelloTo("百里屠苏")
//中缀表达式就是想让代码更加简洁易懂
//加infix后就可以下面这么写
stenve sayHelloTo "百里屠苏"
//自定义操作符、区间、元组
val pair=Pair<String,Int>("百里屠苏",25)
val pair2="百里屠苏" to 25
委托
//这里我们举例小头爸爸把洗碗委托给大头儿子
interface WashPower{
fun wash()
}
class BigHeadSon:WashPower{
override fun wash() {
println("大头儿子洗碗")
}
}
//方式一
//class SmallHeadFather:WashPower by BigHeadSon()
//方式二
class SmallHeadFather(var washPower: WashPower):WashPower by washPower
//--------------------使用
//方式一
// val father=SmallHeadFather()
// father.wash()
//方式二
val bigSon=BigHeadSon()
val smallFather=SmallHeadFather(bigSon)
smallFather.wash()
//类委托加强
class SmallHeadFather(var washPower: WashPower):WashPower by washPower{
override fun wash() {
println("添加一些操作...")
//小头儿子洗碗
washPower.wash()
println("添加一些操作...")
}
}
//属性委托:把当前类字段的get、set方法委托给其它类。
class BigHeadSon:WashPower{
var money:Int by Monther()
override fun wash() {
println("大头儿子洗碗")
}
}
class Monther{
operator fun getValue(bigHeadSon: BigHeadSon, property: KProperty<*>): Int {
return sonMoney
}
operator fun setValue(bigHeadSon: BigHeadSon, property: KProperty<*>, i: Int) {
sonMoney+=i
}
var sonMoney=0
var meMoney=0
}
惰性加载 by lazy
如果一个字段是固定值,我们一般用val,比如val name:String=”haha”,但是这种写法,如果多了,会占内存。这时候可以用by lazy,当使用的时候才会初始化。
惰性加载注意:
- 必须val修饰字段
- by lazy可以放在成员变量中,也可以单独存在
- by lazy返回值就是最后一行
- by lazy是线程安全的
class Person{
val name:String="haha"
val color:String by lazy { "black" }
}
延迟加载
类的字段要么初始化,要么abstract,不然编译不过,但是我可能使用的时候才知道赋什么值,如果现在随便赋值比如var name:String=”“,后面忘记赋值的话问题就可能不在掌握之中了…..
这时候可以使用延迟加载lateinit,使用这个关键字可以不初始化赋值,在使用的时候你没赋值的话会报异常kotlin.UninitializedPropertyAccessException
class Person{
lateinit var name:String
}
by lazy和lateinit比较
- 都可以放在成员变量或者单独使用
- by lazy知道具体值,用的时候加载
- lateinit不知道具体值,用的时候才赋值
- by lazy用val修饰变量,lateinit用var修饰变量
扩展函数
不改变已有类的情况下,为类添加新的函数,扩展函数主要是替代java的util类。子类可以调用父类的扩展函数,但是不能重写。
//格式:类.函数名:返回值
fun String?.isStrEmpty():Boolean{
return this==null||this.length==0
}
val str:String?=null
val isEmpty=str.isStrEmpty()
println(isEmpty)
单例
object单例:Kotlin提供了object单例,所有的字段都是static,方法不是。
所以,object单例有个问题就是如果字段太多,还是有点消耗内存的。所以object单例适用于字段不多的时候。
object Utils{
var name="haha"
fun sayHello(){
println("hello")
}
}
println(Utils.name)
Utils.sayHello()
java中可以控制字段是静态的还是非静态的,Kotlin中没有static关键字。那么怎么控制字段静态和非静态呢?伴生对象。
class Ceshi{
var age=20
companion object {
//静态的字段
var name="hehe"
}
}
我们都知道java中的单例,可以控制只有一个实例,也可以控制字段的静态非静态,那么Kotlin怎么实现像java一样的单例呢?
class Utils private constructor(){
var age=20
companion object {
var name="ahah"
val instance by lazy { Utils() }
}
}
枚举
enum class WEEK{
Mon,Tues,Wed,Thur,Fri,Sat,Sun
}
enum class COLOR(var r:Int,var g:Int,var b:Int){
RED(255,0,0),BLUE(0,0,255),GREEN(0,255,0)
}
println(WEEK.Fri)
val result=WEEK.values()
result.forEach { println(it) }
println(COLOR.GREEN.b)
数据类
class前加data,会默认生成构造函数、get、set、equals、hashCode、toString等。
//数据类
data class News(var title:String,var des:String){
}
//-----------------使用
val news=News("标题","简介")
println(news.title)
println(news.des)
news.component1()//第一个元素
news.component2()//第二个元素
//解构
val (title,des)=News("标题","描述")
println(title)