这个是一些学习笔记。碎碎记。

kotlin与android,现在是kotlin通过插件编译成jvm能运行的机器码,java有的东西kotlin都有。

kotlin支持方法拓展,但是不能写到类里边。写到类里边无效。这个特性非常重要,为拓展提供了新思路。
方法拓展还可以给已有方法重命名,当然,原来方法名还能用,就是包了一层。

fun 类名.拓展方法(args){} //子类可以继承

public var TextView.text: CharSequence  // 拓展 重命名
	get() = getText()
	set(v) = setText(v)

支持lambda,我感觉相当于匿名内部类。

好像要在Javabean的对象前加data

支持对象copy并修改值。

类继承,所有类继承自Any,(不是Object了),默认类不可继承,只有open 或abstract 修饰的类才可以。

函数可以简写了,直接在返回值类型后加=

构造方法和初始化用constructor和init,constructor可以重载

类型转换用as ,安全转换用as?,不成功就是null

静态:

  1. 静态类前边加object;
  2. 一部分是静态方法的情况 : 将方法用 companion object { } 包裹即可,这个叫“伴生对象”,可以给伴生对象起名字,放到object后,也可不加。

bean类不用写getter、setter了, 其实还有,只是不用写,可以重写。

public classs Person {
	var name: String = ""
		get() = field.toUpperCase() 
		set(value){
			field = "Name: $value" 
		}
}

重写用override,加到fun前面

是空安全的,支持?:操作符,和Java里的意思不一样,java里的那个三目运算符只能用if、else表示,但是可以简写

hah?.print() //hah不为空才打印
hah!!/print() //强制打印,可能会有exception
hah?.name?:"null" // null打印null,代替值

//在变量类型后面加上问号,代表该变量是可空变量  可空变量需要强制判null
var name: String? = "zhangsan"  

var lenght:Int = if(haha!=null) haha.length: -1 // 原来java的三目这么用了

with函数,直接使用with括号对象的属性方法。

kotlin强制指定泛型,不加报错

var list = ArrayList<String>()

集合里边有好多拓展方法,map mapto,groupBy,filter很多,详见

kotlin-stdlib-1.1.51-sources.jar!/generated/_Collections.kt

有个库叫anko,这是一个对Android使用kotlin的拓展库,JetBrains开发的。提供了新方式写UI布局。

记一个简化过程
简化 setOnClickListener()

我们用 Android 中非常典型的例子去解释它是怎么工作的:View.setOnClickListener()方法。如果我 们想用 Java 的方式去增加点击事件的回调,我首先要编写一个 OnClickListener 接口:
然后我们要编写一个匿名内部类去实现这个接口:

public interface OnClickListener { 
	void onClick(View v);
}
view.setOnClickListener(new OnClickListener(){ 
	@Override
	public void onClick(View v) {
		Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
 	}
})

我们将把上面的代码转换成 Kotlin(使用了 Anko 的 toast 函数):

view.setOnClickListener(object : OnClickListener { 
	override fun onClick(v: View) {
		toast("Click") 
	}
}

很幸运的是,Kotlin 允许 Java 库的一些优化,Interface 中包含单个函数可以被替代为一个函数。 如果我们这么去定义了,它会正常执行:

fun setOnClickListener(listener: (View) -> Unit)

一个 lambda 表达式通过参数的形式被定义在箭头的左边(被圆括号包围),然后在箭头的右边返
回结果值。在这个例子中,我们接收一个 View,然后返回一个 Unit(没有东西)。所以根据这种思
想,我们可以把前面的代码简化成这样:

view.setOnClickListener({ view -> toast("Click")})

这是非常棒的简化!当我们定义了一个方法,我们必须使用大括号包围,然后在箭头的左边指定参数, 在箭头的右边返回函数执行的结果。如果左边的参数没有使用到,我们甚至可以省略左边的参数:

view.setOnClickListener({ toast("Click") })

如果这个函数的最后一个参数是一个函数,我们可以把这个函数移动到圆括号外面:

view.setOnClickListener() { toast("Click") }

并且,最后,如果这个函数只有一个参数,我们可以省略这个圆括号:

view.setOnClickListener { toast("Click") }

比原始的 Java 代码简短了 5 倍多,并且更加容易理解它所做的事情。非常让人影响深刻。

inline 内联函数, Anko也是基于这个思想来实现的 Android layout 的 DSL 化。

inline fun testInline(code: () -> Unit) {
    code();
}

testInline {
    print("af")
}

委托,标准委托,用by
lazy 懒加载,就是使用的时候才进行调用,一般用于初始化

val datebase: SQLiteOpenHelper by lazy {
    MyDatabaseHelper(applicationContext)
}

observable 观察者


var property by Delegates.observable(""){
    d,old,new ->  // 这个是一个lambda表达式 实际是onchange 源码在下边几行
    database.saveChanges(this,new)
}

// 源码
public inline fun <T> observable(initialValue: T, crossinline onChange: (property: KProperty<*>, oldValue: T, newValue: T) -> Unit):
    ReadWriteProperty<Any?, T> = object : ObservableProperty<T>(initialValue) {
        override fun afterChange(property: KProperty<*>, oldValue: T, newValue: T) = onChange(property, oldValue, newValue)
    }

// 也可以这么写
var property by Delegates.observable("", onChange = {
    property: KProperty<*>, oldValue: String, newValue: String ->
    database.saveChanges(oldValue, newValue)
})

Vetoable 否决器(姑且这么叫吧)用于决定一个值是不是可以赋给变量

//只能是"HAHA"
var onlyHAHA by Delegates.vetoable("", { p, old, new ->
    new == "HAHA"
})

Not Null 指定变量不能为空,为null则抛出异常

var notNull: String by Delegates.notNull()

从Map中获取映射值;map以构造方法的方式传入bean,bean中属性后添加by map,即可自动匹配,if field_name==map.key then:field_value=map.value

自定义一个委托,实现一个值只能修改一次

// 定义
private class NotNullSingleValueVar<T>() : ReadWriteProperty<Any?, T> {
    private var value: T? = null

    override fun getValue(thisRef: Any?, property: KProperty<*>): T {
        return value ?: throw IllegalStateException("not initialized")
    }

    override fun setValue(thisRef: Any?, property: KProperty<*>, value: T) {
        this.value = if (this.value == null) value else throw IllegalStateException("already initialized")
    }

}

//封装
object DelegatesExt {
    fun <T> notNullSingleValue():
            ReadWriteProperty<Any?, T> {
        return NotNullSingleValueVar()
    }
}

// demo
    var notNullSingle: String by DelegatesExt.notNullSingleValue()

object关键字;在参数中,相当于new一个匿名内部类;修饰类,相当于单例模式

view.setOnClickListener(new OnClickListener(){ 
	@Override
	public void onClick(View v) {
		Toast.makeText(v.getContext(), "Click", Toast.LENGTH_SHORT).show();
 	}
})

// 我们将把上面的代码转换成 Kotlin(使用了 Anko 的 toast 函数):
view.setOnClickListener(object : OnClickListener { 
	override fun onClick(v: View) {
		toast("Click") 
	}
}

// 简单单例模式
object Obj{
    init{
        println("object init...")
    }
}

泛型函数
不仅类可以有类型参数。函数也可以有。类型参数要放在函数名称之前:

fun <T> singletonList(item: T): List<T> {
    // ……
}

fun <T> T.basicToString() : String {  // 扩展函数
    // ……
}

//要调用泛型函数,在调用处函数名之后指定类型参数即可:
val l = singletonList<Int>(1)

还有好多不容易理解的特性,以后继续更新。

放个图,哈哈


本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!

一年又一年——2017末 上一篇
非对称加密 下一篇