admin

Kotlin 实战(二):初步认识函数、变量、类
函数Kotlin 是天生支持函数式编程的,所以在 Kotlin 里面,函数是“第一等公民”(first class...
扫描右侧二维码阅读全文
15
2018/02

Kotlin 实战(二):初步认识函数、变量、类

函数

Kotlin 是天生支持函数式编程的,所以在 Kotlin 里面,函数是“第一等公民”(first class)。
所谓"第一等公民"(first class),指的是函数与其他数据类型一样,处于平等地位,可以赋值给其他变量,也可以作为参数,传入另一个函数,或者作为别的函数的返回值(摘自百度百科)。
Kotlin 函数简单声明格式如下:

fun max(a: Int, b: Int): Int {
    return if (a > b) a else b
}

java的函数也没什么好比较,就是一种规范而已,参数以及函数返回值都写在后面,这在其他语言里也是很常见的写法。
以上可以看到,在 Kotlin 中,if是一个表达式,不是一个声明,两者区别就是表达式有值,声明只是一个闭合块的顶层元素,就好比上面的函数声明fun max(a: Int, b: Int): Int部分。在 Kotlin 中循环意外大多数的控制语句都属于表达式,也就是说可以直接用作给表达式赋值或者作为参数,而在java中控制语句全部属于声明。
上面的函数可以进一步简化如下:

fun max(a: Int, b: Int): Int = if (a > b) a else b

这也是 Kotlin 特有的写法,只要记住可以这么写就行了,一个函数返回一个表达式,称之拥有一个表达式主体,如果是一对大括号,就说这个函数有一个块主体。
上面的函数还能加以简化:

fun max(a: Int, b: Int) = if (a > b) a else b

可以看到,我们省掉了函数返回值类型的声明,这在 Kotlin 中是允许的,编译器会在编译时分析表达式的值类型,然后用作函数的返回值类型,这就是 Kotlin 中的类型推断
但是需要注意的是只有表达式主体的函数才能够省去返回值类型的书写,如果是块主体的函数,则必须明确指出返回值类型声明,并且在快主体内要返回的值的前面加上return声明。

变量

以下简单声明两个变量:

val str = "Hello World!"
val age = 24

java不同,java声明变量时需要将变量类型写在前面,而在Kotlin中,都是以valvar关键字开始来声明变量的,类型放在变量名后面,在上面的声明中,和有着表达式主体的函数声明一样,我们可以省去类型的声明,当然,下面的写法也是可以的:

val str: String = "Hello World!"
val age: Int = 24

需要注意的是,如果在声明变量的时候没有赋值,那么就必须显式指定变量类型:

val age: Int
age = 42

上面说到Kotlinvalvar两个关键字来声明变量,两者的区别如下:

  • val:不可变的引用,初始化后不能重新分配值,相当于 Java 中的 final 变量
  • var:可变的引用,初始化后的值可以再次改变,相当于 Java 中的 非 final 变量

注意,val不可变是指其引用地址不可变,但它引用地址所指向的对象可能是可变的,比如:

val list = arrayListOf("Kotlin")
list.add("C++")
在字符串模板中使用变量
val name = "Kotlin"
println("Hello $name")

和其他脚本语言非常类似,Kotlin字符串模板支持用$美元符号来使用变量,甚至是一个表达式(和JSP中的EL表达式非常类似):

val a = 2
val b = 6
println("max value is: ${if (a > b) a else b}")

以上就是变量的简单使用。

首先,看一个熟悉的Java类写法:

public class Person {

    private final String name;
    
    public Person (String name) {
        this.name = name;
    }
    
    public String getName() {
        return name;
    }
}

Kotlin中我们可以这样写:

class Person(val name: String)

对比一下上面的两种写法,在java中构造器赋值的代码通常是完全重复的,就是将参数的变量赋值给对应名字的字段,而Kotlin使用如上写法就和上面的java代码完全是等价的。
Kotlin中,类的public修饰器是默认的,因此可以省略掉。

属性

类的思想就是封装数据以及将数据转化为单一实体。
java中,通常数据是存储到私有字段中的,如果需要给客户端使用的话就直接提供gettersetter方法,一般变量提供获取和设置访问器,常量只需提供getter获取器。这种字段和字段的访问器常被称为属性。并且,这种代码的生成对程序员来说经常是重复性的。
而在Kotlin中,大大简化了我们的代码,它将字段和字段的访问器结合起来了(在 Kotlin 中直接称为属性),即我们只需声明属性即可,访问器会根据声明的关键字valvar自动生成(不会显示出来,但我们可以直接使用),如下:

class Order(val num: String, var isFinished: Boolean)

fun main(args: Array<String>) {
    val o = Order("20180215000001", true)
    println(o.num + ", " + o.isFinished)
}

其实使用方式就和java类中的public字段的用法差不多,这里可能会有个疑惑:如果java字段直接声明为public,那么不就没多大区别了吗?这个疑惑我也暂且不知,这样的写法是否破话了类的封装性,在《Kotlin in Action》中并未提及,有知道的大神请帮忙讲解一下。
我测试过如下代码:

class Order(private val num: String, var isFinished: Boolean)

num前加上private修饰符,这样一来o.num将会报错,所以我猜测Kotlin上面的那种写法所声明的字段将全部默认是public类型的,那么是否破坏了类的封装性呢?希望学到后面能够找到答案吧。

自定义获取器
class Rectangle(var width: Int, var height: Int) {
    val isSquare: Boolean
        get() {
            return width == height
        }
}

fun main(args: Array<String>) {
    val rectangle = Rectangle(1, 1)
    println(rectangle.isSquare)
    rectangle.height = 2
    println(rectangle.isSquare)
}

输出结果:

true
false

如上代码,isSquare属性是由自定义获取器计算获得的,虽然用val声明,但每次获取还是会重新计算,这里也必须用val关键字,用var关键字将会报错,书中也并未说明,总之也就一笔带过,自己尝试过在类中使用valvar声明属性,全部都要初始化设置值,这也是与java不同的地方。
到此,Kotlin中的类绝非如此简单,由于跟随《Kotlin in Action》一书学习,书中此时还并未深入讲解Kotlin的类,但此时心中已经存在着多个疑惑了。

小结

以上仅仅对Kotlin中的函数、变量、类有了一个初步的了解,心中疑惑甚多,加油学习从日后的学习中寻找答案吧!

Last modification:February 15th, 2018 at 02:06 am
If you think my article is useful to you, please feel free to appreciate

Leave a Comment