类和对象
类
在Kotlin中,类依旧使用class定义,用大括号包裹,不过当类里面没有任何代码时,大括号可以省略。
构造函数
Kotlin中可以有一个主构造函数和多个二级构造函数,如下:
1 | class A constructor(name: String){ |
其中的constructor
关键字可以省略。但是如果构造函数有其他声明获取注解,如:private
,那么constructor
就不能省略。
在主构造函数中不能有任何代码,所以初始化代码需要写在init
代码块中,或者在参数声明时定义:
1 | class A (name: String){ |
属性声明可以主构造函数中直接声明:
1 | class A (var userName: String){ |
二级构造函数声明在类体内,但是必须有constructor
关键字,如下:
1 | class A { |
如果类已经有了一级构造函数,那么二级构造函数在声明时必须代理主构造函数,并且使用关键字this
:
1 | class A (var name: String){ |
两个构造函数在使用时没有区别,所以在声明时参数数量或类型需要不同。
在创建类的实例时,不需要关键字new,可以直接创建。
1 | val a=A("tim") |
属性和字段
类中的属性用var声明时可变的,用val声明是只读的。使用属性时只要直接用名称使用它即可,如:a.userName
。
声明属性的示例:
1 | var userName: String?=null |
在确定了属性的类型后,必须要指定其默认值。
get和set方法
除了在声明属性时指定默认值以外,还可以在get方法中设置值。Kotlin中get和set方法都是默认的,但是我们也可以自定义get和set方法。
1 | var userName: String? |
这里userName
开始没有默认值,但是在get方法中设置了值。
1 | var userName: String?=null |
这里userName
传入的值后面添加一个.
如果你需要改变一个访问器的可见性或者对其注解,但是不需要改变默认的实现, 你可以定义访问器而不定义其实现:
1 | var userName: String?=null |
数据类
我们经常创建一些只保存数据的类。在这些类中,一些标准函数往往是从 数据机械推导而来的。在 Kotlin 中,这叫做数据类
并标记为data
:
1 | data class User(val name: String, val age: Int) |
编译器自动从主构造函数中声明的所有属性导出以下成员:equals()/hashCode() 对,toString() 格式是 “User(name=John, age=42)”,componentN() 函数 按声明顺序对应于所有属性,copy()函数。
对于上面的数据类,程序会自动生成copy
函数:
1 | fun copy(name: String = this.name, age: Int = this.age) = User(name, age) |
copy
方法使用如下:
1 | val jack = User(name = "Jack", age = 1) |
密封类
密封类用来表示受限的类继承结构:当一个值为有限集中的类型、而不能有任何其他类型时(所有的子类都必须在密封类的内部,继承子类的类可以在其他文件)。
1 | sealed class Expr |
使用密封类的关键好处在于使用 when 表达式 的时候,如果能够验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。
嵌套类
类可以嵌套在其他类中
1 | class Outer { |
内部类
类可以标记为inner
以便能够访问外部类的成员,这个类就是内部类。内部类会带有一个对外部类的对象的引用:
1 | class Outer { |
匿名内部类
对象表达式创建匿名内部类:
1 | window.addMouseListener(object: MouseAdapter() { |
函数
Kotlin 中的函数使用 fun 关键字声明
1 | fun setName(name: String) : Int{ |
后面的: Int
表示返回值为Int,如果不返回任何值,则使用Unit
,如:
1 | fun setName(name: String) : Unit{ |
函数在声明时可以直接设置默认参数,如:
1 | fun setName(name: String="tim") : Unit{ |
覆盖方法总是使用与基类型方法相同的默认参数值。 当覆盖一个带有默认参数值的方法时,必须从签名中省略默认参数值。
可以在调用函数时使用命名的函数参数。当一个函数有大量的参数或默认参数时这会非常方便。如:
1 | fun setName(name: String="tim",a: Boolean=false,b: Boolean=false,c: String) : Unit{ |
使用命名参数,增加可读性,同时也可以省略部分参数,如:
1 | a.setName("ddd",c="d") |
当函数返回单个表达式时,可以省略花括号并且在 = 符号之后指定代码体即可,如:
1 | fun double(x: Int): Int = x * 2 |
函数的参数还可以使用Varargs
来表示可变数量的参数,如:
1 | fun <T> asList(vararg ts: T): List<T> { |
在 Kotlin 中函数可以在文件顶层声明,所有你不需要用类来保存一个函数。此外 除了顶层函数,Kotlin 中函数也可以声明在局部作用域、作为成员函数以及扩展函数。而顶层函数在调用时不需要实例就可以直接调用。
Kotlin 支持局部函数,即一个函数在另一个函数内部。如:
1 | fun dfs(graph: Graph) { |