前言
方法支持默认参数:
fun toast(context: Context = this, text: String, time: Int = Toast.LENGTH_LONG) {
Toast.makeText(context,text,time).show()
}
fun test(){
toast(text = "土司提示")
toast(this, text = "土司提示")
toast(this, text = "土司提示", Toast.LENGTH_SHORT)
}
类方法扩展:
// 扩展String类的方法
private fun String.handle(): String {
return "$this handle"
}
fun main() {
println("Test".handle())
}
函数变量:
var result = fun(number1: Int, number2: Int): Int {
return number1 + number2
}
@Test
fun main() {
println(result(1, 2))
}
内联函数
fun main() {
// 参数是函数类型的
showToast({ println("test") }, "test")
}
/**
* 内联函数用inline修饰:
* 编译的时候将所有的inline里的代码直接copy进去。方法调用栈减少。
* 适合:对性能的影响微不足道。适用于参数为函数类型的函数(lambda)。
* 不适合:一些频繁调用的函数(很多地方都在调用)或者体量比较大的函数,copy会增加代码量
*
*/
private inline fun showToast(function: () -> Unit, message: String) {
function.invoke()
println(message)
}
参数是函数类型的函数,不加inline会导致多生成一个内部类,是lambda函数多出来的类,并且还是静态,会增加内存消耗,inline可以减少一层方法栈的调用(虽然对性能微不足道)。
inline(内联)和noinline(进制内联)。noinline是修饰在lambda参数上面,inline函数有多个lambda参数,只对某个lambda参数不内联,可以用noinline修饰。
private inline fun showToast(function1: () -> Unit,noinline function2: () -> Unit, message: String) {
function1.invoke()
function2.invoke()
println(message)
}
密封类
fun main() {
val result = if (isDebug) {
Result.SUCCESS("get data success")
} else Result.FAIL("get data fail")
when (result) {
is Result.SUCCESS -> {
println(result.data)
}
is Result.FAIL -> {
println(result.throwable)
}
}
}
/**
* 密封类(可以带参数,根据需要修改) 类似于java的枚举(类型固定,不能带参数)
*/
sealed class Result {
data class SUCCESS(val data: String) : Result()
data class FAIL(val throwable: String) : Result()
}
类委托
fun main() {
val logStrategyImpl = LogStrategyImpl()
LogStrategyProxy(logStrategyImpl).log("test")
}
/**
* 接口
*/
interface ILogStrategy{
fun log(msg:String)
}
/**
* 实现ILogStrategy接口
*/
class LogStrategyImpl:ILogStrategy{
override fun log(msg: String) {
println(msg)
}
}
/**
* 类委托:把LogStrategyProxy对ILogStrategy实现,委托给参数strategy来实现。所以LogStrategyProxy虽然是接口ILogStrategy
* 的子类,但是内部不需要自己区实现,把实现委托给自己的参数来实现。
*/
class LogStrategyProxy(strategy: ILogStrategy):ILogStrategy by strategy
属性委托
fun main() {
// 属性委托 temp对象的创建委托给XxxDelegate类来做。
var temp: String by XxxDelegate()
println("temp:$temp")
temp = "555"
println("temp:$temp")
}
class XxxDelegate {
private var currentValue: String = "default"
operator fun getValue(thisRef: Any?, property: KProperty<*>): String {
print("getValue $currentValue")
return currentValue
}
operator fun setValue(thisRef: Any?, property: KProperty<*>, newValue: String) {
currentValue = newValue
println("setValue $currentValue")
}
}
懒委托
fun main() {
// 懒委托:和懒汉式类似
val temp: String by lazy {
println("init")
return@lazy "555"
}
println("temp:$temp")
}
// 懒委托最适合用findViewById
private val textView:TextView?by lazy {
findViewById(R.id.main)
}
懒委托几种加载模式:
- LazyThreadSafetyMode.SYNCHRONIZED:同步模式,确保只有单线程可以初始化实例,初始化时线程安全的,默认使用这种模式。
- LazyThreadSafetyMode.PUBLICATION:并发模式,在多线程允许并发初始化,但是只有第一个值返回的值作为实例,这种模式下时线程安全的,多线程并发访问效率最高,空间换取时间,那个线程快就先返回哪个,其他线程执行结果抛弃。
- LazyThreadSafetyMode.NONE:普通模式,不会用锁来线程多线程访问,线程不安全的,请勿在多线程并发情况下使用。
使用懒委托变量必须声明为val(不可变),因为它只能被赋值一次。
高阶函数
高阶函数是kotlin简化代码的写法:let with run apply also五个常用函数。
let函数
fun main() {
// 函数块里用it指代该对象,函数最后一行return返回。
// 处理针对一个可null对象一些列操作:.?let{}
val result = "test".let {
println("it:$it")
1000
}
println("result:$result")
}
with 函数
fun main() {
// with函数内用this(可省略调用该对象的属性)指代该对象,最后一行是返回值
// 可以省略类名重复,例如:RecyclerView.onBinderViewHolder中,数据model的属性映射到UI上
val result = with(Person("test",100)){
println("name:${this.name} age:$age")
1000
}
println("result:$result")
}
class Person(var name:String,var age:Int)
run函数
fun main() {
val person = Person("test",18)
/**
* run适合于let,with函数任何场景。
*/
val result = person.run {
println("name:$name")
1000
}
println("result:$result")
}
class Person(var name:String,var age:Int)
apply函数
fun main() {
// apply返回对象本身
// 如:inflate一个xml的view,并返回View。多层级判空等
val person = Person("test",18).apply {
name = "test1"
age = 20
}
}
also函数
fun main() {
// also 返回值是传入对象本身。一般用于链式调用
val result = "test".also {
println(it.length)
}
println("result:$result")
}
运算符重载
fun main() {
val a = 1
val b = 2
// a++
a.inc()
// a--
a.dec()
// a+b
a.plus(b)
}