1.方法的定义
使用fun关键字定义,取自英文function;
fun me():String{ return "" }
如上:返回值类型为String,大括号为方法体,若函数没有返回值,则返回值使用Unit修饰,可省略不写;
2.类的写法
class Person constructor(
var name:String,
var age :Int,
var sex :String
)
(1)小括号中跟着的是该类的主构造函数,主构造函数没有可见性修饰,没有注解,可以省略construct;
(2)大括号中没有内容,也可以省略;
(3)若构造函数中的属性全部都有初始化值,则该类会有一个默认的无参构造,属性值为默认值;否则没有无参构造;
若有部分属性没有初始化,则会自动补充一个只有该属性的构造函数;
(4)对于类初始化是要执行的方法,在大括号init(){}方法中可以写;
class Person constructor(
var name:String,
var age :Int,
var sex :String
){
init {
println("我出生了")
}
}
(5)默认的类都是final的,若要被继承,类前用open修饰, open class Person... ...
(6)创建类与java不同的是省略了 new 关键字;
(7)对于数据类,可以用data修饰类,
data class Person(
var name:String = "小明",
var age :Int = 0,
var sex :String = "man"
)
fun main(args: Array<String>) {
println(Person())
}
输出为:Person(name=小明, age=0, sex=man)
编译器会自动的从主构造函数中根据所有声明的属性提取以下函数:
equals()
/hashCode()
toString()
格式如"User(name=John, age=42)"
componentN() functions
对应于属性,按声明顺序排列copy()
函数
对于data修饰的数据类,有以下限制:
-
主构造函数至少包含一个参数。
-
所有的主构造函数的参数必须标识为
val
或者var
; -
数据类不可以声明为
abstract
,open
,sealed
或者inner
;
在官方文档中有如下一句话: 数据类不能继承其他类 (但是可以实现接口)
open class Person( var name:String = "小明", var age :Int = 0, var sex :String = "man" ) data class Child constructor(var weight:Double = 0.0):Person(name = "345")
但该继承也没有报错;
(8)getter/setter方法
class Dog{
var name:String = "Anny" //var 声明变量为可变变量
get() {return field.toUpperCase()} //fidle代表的是当前的属性字段
set(value) {field = value} //可以自定义set方法
var sex:String = "man"
get() = field.toUpperCase()
set //默认的set方法
val Dogger:Double = 0.0 //val 修饰与java中final一样,为不可变量,没有set方法
}
(9)抽象类
与java相同用abstract修饰类,抽象类省略open修饰,默认是非final的可继承;
(10)接口
与java相同用interface修饰,省略open修饰,默认是非final的可实现;
(11)内部类
使用inner修饰,inner class
3.继承
(1)由于kotlin中类默认为final的,所以父类要被继承必须声明为open;
(2)继承采用':'标识,属性默认值为父类的属性默认值;
class Child constructor(var weight:Double = 0.0):Person()
fun main(args: Array<String>) {
println(Child().name) //在java中为getName(),但在kotlin中可以直接调用属性,默认调用get方法
}
输出为:小明
(3)若要在子类改变默认值,
//从继承处将字段传进来
class Child constructor(var weight:Double = 0.0,name: String = "小李"):Person(name)
(4)方法的重写
在kotlin中,类是默认final的,同时类中的方法也都是默认final的,也就是不可重写,如果需要重写方法,需要将父类方法声明为open,同时在子类重写的方面前面声明override;
//父类
open class SystemService{
open fun doOverride():String{
return "index"
}
}
//子类
class SystemServiceImpl: SystemService() {
override fun doOverride():String{
return "index"
}
}
4.密封类
密封类用来表示受限的类继承结构:当一个值为有限几种的类型, 而不能有任何其他类型时。在某种意义上,他们是枚举类的扩展:枚举类型的值集合 也是受限的,但每个枚举常量只存在一个实例,而密封类 的一个子类可以有可包含状态的多个实例。
声明一个密封类,使用 sealed 修饰类,密封类可以有子类,但是所有的子类都必须要内嵌在密封类中。
sealed 不能修饰 interface ,abstract class(会报 warning,但是不会出现编译错误)
sealed class Number
class NumInt :Number()
class NumDouble : Number()
fun test(n:Number) = when(n){
is NumInt -> println()
is NumDouble -> println()
}
使用密封类的关键好处在于使用 when 表达式 的时候,如果能够 验证语句覆盖了所有情况,就不需要为该语句再添加一个 else 子句了。
当判断条件可知是有限的可能条件时,kotlin可以自动识别所有的情况,例如枚举类的情况判断:
enum class Number{
INT,DOUBLE,BYTE
}
fun test(n:Number) = when(n){
Number.INT -> println()
Number.BYTE -> println()
Number.DOUBLE -> println()
//此处可以省略else,在java中类似default的处理情况,
//但是当上面的条件没有全部覆盖时,需要使用else,不然编译会报错,这也是智能于java的一个地方,避免遗漏场景
}
5.kotlin 接口
在kotlin中接口的规则与java8特性一致,可以有默认的方法实现,但无需default修饰,直接给出方法体就好;
open interface SystemService{
fun test()
fun doIndex():String{
return "index"
}
}
实现接口的方式和继承相同,使用 : 标识符号;
class SystemServiceImpl: SystemService {
override fun test() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}
}
实现接口中的方法需要使用override修饰方法;