Kotlin一些基本语法

来源:互联网 发布:网络营销策划案 汽车 编辑:程序博客网 时间:2024/04/28 14:20
首先要在AS中搜索安装插件Kotlin

配置gradle:https://github.com/wangjiegulu/kotlin-for-android-developers-zh/blob/master/pei_zhi_gradle.md

1.JAVA代码转Kotlin:
将需要转换的文件打开为当前文件,点击Code---Convert JAVA file to Kotlin

2.定义一个类,依然使用关键字class:
class Person{}   (类没有内容时这个大括号可以省略)

需要注意的是类的构造器问题,和JAVA一样,类有自己无参的默认构造器。但是对于这个构造器方法体的编写是在init模块中:
init{
}
也可以在定义时指定构造器接收的参数:class Person(a:String,b:String)
构造器是需要关键字constructer的,类定义时的构造器是主构造器,可以省略这个关键字。可是有可见性声明的时候这个关键字不能省略。除了主构造器还有类中的二级构造器:
class Person {    constructor(parent: Person) {        parent.children.add(this)    }}
通常我们需要定义一个变量然后通过构造器传入赋值,这时可以直接在主构造器参数加关键字var和val,这样就成为可以全局使用的变量了。
如果有主构造器的话,次级构造器必须进行代理,在调用次级构造器时,主构造器会得到调用:
class Test(var s:String){    init {        print("构造器1"+s)    }    constructor(a:String,b:String) : this(a){        print("构造器2")    }}

如果无主构造器,默认会有一个无参public构造器。如果不想产生这个构造器,可以使用私有的()空作为主构造器:


通常习惯于在数据类的前面加关键字data,编译器会根据构造器中的参数生成合适的toString,equals


3.继承:所有l类有共同父类Any,就像Object一样。类默认是不能被继承的,只能声明成open或abstract的类才能被继承。
 open class Person{}class A : Person()
当父类构造器有参数时,子类构造器需要接收并将这个参数传递给父类构造器(编译器会检查):
 open class Person(a:String){}class A(a: String) : Person(a)

子类二级构造器对父类构造器调用:
constructor(ctx: Context) : super(ctx) {    }
还有子类重写父类方法的问题,方法默认是不能被子类重写的,必须声明关键字为open。


4.函数
fun add(x: Int, y: Int) : Int {    return x + y}
语言中的函数和成员都看做对象,关键字是fun,可以在括号后面指定返回值,返回依然使用return。不设返回值的话默认返回Unit,类似于void,但是Unit是一个真正的对象。
如果方法体是一个表达式返回值的话可以简写为:
fun add(x: Int,y: Int) : Int = x + y
如上所示,参数先写参数名然后用冒号给出参数类型。
参数可以设置默认值,设置默认值的参数在调用函数时可以忽略,也就是不传入:
fun toast(message: String, length: Int = Toast.LENGTH_SHORT) {    Toast.makeText(this, message, length).show()}
这主要是可以省去一些重载,只需要写参数最多的方法。
还有一种使用技巧:当参数列表有好几个参数时,可以通过使用参数名来选择传入哪几个参数:
fun niceToast(message: String,                tag: String = javaClass<MainActivity>().getSimpleName(),                length: Int = Toast.LENGTH_SHORT) {    Toast.makeText(this, "[$className] $message", length).show()}
来源: https://github.com/wangjiegulu/kotlin-for-android-developers-zh/blob/master/gou_zao_fang_fa_he_han_shu_can_shu.md
toast(message = "Hello", length = Toast.LENGTH_SHORT)
见上,这里通过参数名调用了第一个和第三个参数。

5.变量和实例化
变量的关键字是var,动态类型,val是常量,类似于JAVA的final。应该尽量多使用val
可以显示指定变量类型:val i:Int = 7  也可以不指定,让编译器去判断
和JAVA不同,字符不能作为数值使用,位运算也不使用&|而是and or
实例化与JAVA的不同是不用写new:
var a=A()

可为空标识:变量定义或者函数的参数返回值,都可以使用类型后面加问号(Int?)表示可以为空。

6.属性:
对于属性的访问只需要直接使用person.name这样调用。但是其实他并不是直接访问属性,而是和JAVA规范一样经过getter and setter。KOTLIN中默认对属性提供了这两个方法,我们也可以自行修改,这两个方法要紧跟在变量后:
var name: String = ""    get() = field.toUpperCase()    set(value){        field = "Name: $value"    }

这里使用了field这个伪变量来引用变量。get和set方法的重写格式就是这样的,都是可选的。val不支持set方法,因为只读。
备用字段用field表示

非空变量必须立即初始化,如果不想的话可以用lateInit关键字修饰,不支持基本数据类型。

7.类型判断:可以使用A is B来进行对象的类型判断,有趣的是检查后如果结果为真,那么这个对象可以直接调用检查类型的方法而不需要显式转换(看做这个类型)。

8.循环:for循环:for (item in items) {
    println(item)  }
使用in 关键字直接取出集合中的元素。
遍历map:for((x,y)  in map)
也可以使用while,用法和JAVA相同。可以用continue和break
在需要Index的情况下遍历(借用withIndex函数):
for((index,value) in list.withIndex())

while/do while和JAVA一样。

9.in关键字
上面提到in可以用于遍历容器取出数据。也可以用于判断元素是否在容器中,A IN B这个表达式是有一个布尔返回值的。

10.when:类似于JAVA中的switch,对目标对象进行匹配判断,找到符合条件的分支,可以看到,这里用is关键字对目标进行类型匹配,也可以用in或者其他有真假的表达式匹配,没有限制:
when (x) {     Foo ->  ...     Bar -> ...    else -> ...}
when是可以作为值来出现在等号右侧的,返回匹配到的函数或者数据
类似的。else相当于switch的default。另外,如果有几个条件处理相同,可以用逗号隔开放在一项:
when (x) {     Foo,A ->  ...     Bar -> ...    else -> ...}
也可以把一个区间作为一个分支,如:in 1..10或!in1..10
还可以判断是否属于某个类型:is String
根据顺利判断的特性可以用when取代if-else链。
还可以不要x的情况下进行判断:
1
when {
2
        "orange" in items -> println("juicy")
3
        "apple" in items -> println("apple is fine too")
4
    }


if也可以为对象赋值 ,他的值是匹配到的代码部分的最后一行:
val max = if (a > b){    print("Choose a")    a}else{    print("Choose b")    b}
这意味着可以用if取代JAVA中的三目运算符:
var a=if(...) 1 else 2

11.延迟加载(懒属性) 属性在之后进行赋值:使用by lazy
val p: String by lazy {    // 生成string的值}

12.基本类型:需要格外注意的是,数值之间不存在JAVA一样的隐式转换,想要将一种数值赋给另一种数值,必须进行显式的转换,可以通过toInt这样的方法实现。字符也不能当做数值使用。

13.字符串模板:字符串中可以有表达式,跟在$后面,$加一个变量或者一个花括号括起来的表达式(有计算结果),在处理字符串的时候变量或者表达式的值会计算出来,然后拼接在字符串中。

14.返回:一般来说return会跳出整个函数,但是借助标签可以调到指定的函数层级。:
fun foo() {    ints.forEach lit@ {        if (it ==0) return@lit        print(it)    }}
添加了lit标签,这样就跳出了内层函数,而还在外层函数中。
甚至可以不用在方法名后加标签,返回标签用方法名:
foo outer() {    foo inner() {        return@outer    }}



15.Anko和扩展函数
Anko提供了一系列扩展函数来简化一些常用操作。扩展函数是对一个类的行为的扩展,他可以定义在任何位置,相关对象在调用时可以直接调用。如:
fun Context.toast(message: CharSequence, duration: Int = Toast.LENGTH_SHORT) {    Toast.makeText(this, message, duration).show()}
定义了这个函数后,所有活动都可以直接toast(...)来使用这个方法。这就是Anko背后的原理。因为语言的一个突出特点就是空安全,所有可能为空的地方都需要指出。

16.子线程切换:
KOTLIN中的开启子线程非常简单,anko提供了一个sync函数来处理子线程任务,在里面调用uiThread就能回到主线程,非常方便:
async {    network()    uiThread {        toast("aaa")    }}

uiThread有一个突出的优点就是执行前会检查依赖的activity是否finish,如果finish则不会调用,这样就避免了活动销毁时崩溃。
如果希望异步任务得到一个Future的返回值,则使用asyncResult

17.比较:
首先kotlin中没有基本数据类型,每一个定义的数值实际都对应着一个封装的对象。
关于比较,两个等号表示数值的比较,三个等号表示地址的比较,也就是对象是否相同的比较。
两个数值一样的不同Int,==比较为真,===比较为假
需要注意的是,跟 Java 中是一样的,在范围是 [-128, 127] 之间并不会创建新的对象,比较输出的都是 true,从 128 开始,比较的结果才为 false。

18.数组
声明:var a:Array<String>,除了这种使用泛型的数组声明,还有IntArray等数组类型,在处理相应的数据时更加高效。

初始化:有两种方式,一种是使用arrayOf (intArrayOf):
    a=arrayOf("dhuwei","adjioaewd")
    另一种是使用构造函数:a=Array(10,{ i -> ("djopwqed")})。第一个       参数是数组长度,第二个箭头函数接收index并返回相应项的值。

get与set:和JAVA一样。

19.特殊类
抽象类和JAVA一样,用abstract修饰。
内部类用关键字inner修饰,内部类对象可以this@+外部类类名 来获得外部类对象。

20.接口
接口依然用interface修饰,不同的是方法可以实现,也就是可以有默认的实现。
接口的实现和继承相似,放在类名冒号后面即可。
接口中的属性只能是抽象的,不允许初始化值,接口不会保存属性值,实现接口时,必须重写属性:

原创粉丝点击