4.Kotlin_表达式&关键字

if表达式

Kotlin中,if是一个表达式,即它会返回一个值,每个条件分支都隐式地返回其最后一行的表达式的结果,因此无需使用return关键字。因此就不需要三元运算符条件 ? 然后 : 否则,因为普通的if就能胜任这个角色。 if的分支可以是代码块,最后的表达式作为该块的值:

val max = if (a > b) {
    print("Choose a")
    a
} else {
    print("Choose b")
    b
}

when表达式

when表达式与Java中的switch/case类似,但是要强大的多。这个表达式会去试图匹配所有可能的分支直到找到满意的一项。 然后它会运行右边的表达式。
Javaswitch/case不同之处是参数可以是任何类型,并且分支也可以是一个条件。

对于默认的选项,我们可以增加一个else分支,它会在前面没有任何条件匹配时再执行。条件匹配成功后执行的代码也可以是代码块:

when (x){
    1 -> print("x == 1") 
    2 -> print("x == 2") 
    else -> {
        print("I'm a block")
        print("x is neither 1 nor 2")
    }
}

因为它是一个表达式,它也可以返回一个值。我们需要考虑什么时候作为一个表达式使用,它必须要覆盖所有分支的可能性或者实现else分支。否则它不会被编译成功:

val result = when (x) {
    0, 1 -> "binary"
    else -> "error"
}

如你所见,条件可以是一系列被逗号分割的值。但是它可以有更多的匹配方式。比如,我们可以检测参数类型并进行判断:

when(view) {
    is TextView -> view.setText("I'm a TextView")
    is EditText -> toast("EditText value: ${view.getText()}")
    is ViewGroup -> toast("Number of children: ${view.getChildCount()} ")
    else -> view.visibility = View.GONE
}

示例:when对if else的改造

fun schedule(day: Day, sunny: Boolean) = {
    if (day == Day.SAT) {
        basketball()
    } else if (day == Day.SUN) {
        fishing()
    } else if (day == Day.FRI) {
        appointment()
    } else {
        if (sunny) {
            library()
        } else {
            study()
        }
    }
}

上面的例子中因为存在不少if else分支,代码显得不够优雅,更好的改进方法是用when表达式来优化:

fun schedule(sunny: Boolean, day: Day) = when (day) {
    Day.SAT -> basketball()
    Day.SUN -> fishing()
    Day.FRI -> appointment()
    else -> when {
        // when关键字的参数可以省略
        sunny -> library()
        else -> study()
    }
}

一个完整的when表达式类似switch语句,由when关键字开始,用花括号包含多个逻辑分支,每个分支由-> 连接, 不再需要switch的break(这真是一个恼人的关键字),由上往下匹配,一直匹配完为止,否则执行else分支的逻辑,类似switch的default。

到这里你可能会说上面的例子中,这样嵌套子when表达式,层次依旧比较深。要知道when表达式是很灵活的,我们很容易通过如下修改来解决这个问题:

fun schedule(sunny: Boolean, day: Day) = when {
    day == Day.SAT -> basketball()
    day == Day.SUN -> fishing()
    day == Day.FRI -> appointment()
    sunny -> library()
    else -> study()
}

这样就会更优雅了。

for循环

val items = listOf("apple", "banana", "kiwi")
for (item in items) {
    println(item)
}

for (i in array.indices)
    print(array[i])

在Kotlin中用in关键字来检查一个元素是否是一个区间或集合中的成员。如果我们在in前面加上感叹号,那么就是相反的判断结果。

Ranges

Range表达式使用一个..操作符。表示就是一个该范围内的数据的数组,包含头和尾:

var nums = 1..100 
for(num in nums) {
    println(num)
    // 打印出1 2 3 ....100
}
if(i >= 0 && i <= 10) 
    println(i)

转换成

if (i in 0..10) 
    println(i)

Ranges默认会自增长,所以如果像以下的代码:

for (i in 10..0)
    println(i)

它就不会做任何事情。但是你可以使用downTo函数:

for(i in 10 downTo 0)
    println(i)

我们可以在Ranges中使用step来定义一个从1到一个值的不同的空隙:

for (i in 1..4 step 2) println(i)
for (i in 4 downTo 1 step 2) println(i)

Until

上面的Range是包含了头和尾,那如果只想包含头不包含尾呢? 就要用until:

var nums = 1 until 100
for(num in nums) {
    println(num)
    // 这样打印出来是1 2 3 .....99
}

上面in、step、downTo、until这几个,他们可以不通过点号,而是通过中缀表达式来被调用,从而让语法变得更加简洁直观。

Kotlin用到的关键字

  • var:定义变量
  • val:定义常量
  • fun:定义函数
  • Unit:默认方法返回值,类似于Java中的void,可以理解成返回没什么用的值类型
  • vararg:可变参数
  • $:字符串模板(取值)
  • 位运算符:or(按位或),and(按位与),shl(有符号左移),shr(有符号右移),
  • ushr(无符号右移),xor(按位异或),inv(按位取反)
  • in:在某个范围中 检查值是否在或不在(in/!in)范围内或集合中
  • downTo:递减,循环时可用,每次减1
  • step:步长,循环时可用,设置每次循环的增加或减少的量
  • when:Kotlin中增强版的switch,可以匹配值,范围,类型与参数
  • is:判断类型用,类似于Java中的instanceof()is运算符检查表达式是否是类型的实例。 如果一个不可变的局部变量或属性是指定类型, 则不需要显式转换
  • private仅在同一个文件中可见
  • protected同一个文件中或子类可见
  • public所有调用的地方都可见
  • internal同一个模块中可见
  • abstract抽象类标示
  • final标识类不可继承,默认属性
  • enum标识类为枚举
  • open类可继承,类默认是final
  • annotation注解类
  • init主构造函数不能包含任何的代码。初始化的代码可以放到以init关键字作为前缀的初始化块(initializer blocks)中
  • field只能用在属性的访问器内。特别注意的是,get set方法中只能使用filed。属性访问器就是get set方法。
  • :用于类的继承,变量的定义
  • ..范围操作符(递增的) 1..52..6千万不要6..2
  • ::作用域限定符
  • inner类可以标记为inner {: .keyword }以便能够访问外部类的成员。内部类会带有一个对外部类的对象的引用
  • object对象声明并且它总是在object{: .keyword }关键字后跟一个名称。对象表达式:在要创建一个继承自某个(或某些)类型的匿名类的对象会用到

results matching ""

    No results matching ""