-
-
kotlin类定义由类名,类头(指其范型声明、主构造器等)和用花括号包围的类体构成。类头和类体都是可选的。空类没有实际意义。
- 属性用于定义该类的对象所包含的状态数据。
- 方法定义该类的行为特征或者功能实现。
- 构造器用于构造该类的对象。
一个类有0-1个主构造器和0-N个次构造器,主构造器是类头的一部分,跟在类名(和范型声明)后。
class User constructor(first: String){}
- kotlin类大致有如下作用:
- 定义变量
- 创建对象
- 派生子类
- 创建对象的根本途径是构造器,调用某个类的构造器便可创建这个类的对象,无须使用new关键字。
class Person{ var name: String = "" var age: Int = 0 fun say(content:String){ println(content) } } var p:Person p = Person()
-
-
this关键字:作为对象的默认引用有两种形式:
- 在构造器中引用改构造器正在初始化的对象。
- 在方法中引用调用该方法的对象。
-
方法是类或者对象行为特征的抽象。kotlin方法与函数是统一的。不仅定义函数和方法的语法相同,而且定义在类中的方法依然可独立出来。也就是说,即时我们将方法定义在类里面,这个方法也依然可以转化为函数。
fun main(){ var rn:(Dog)->Unit = Dog::run var dog = Dog() rn(dog) var en = Dog::eat en(dog,"骨头") } class Dog{ fun run(){ println("run 方法") } fun eat(str:String){ println("eat 方法,吃$str") } }
-
中缀表示法 方法中用infix修饰后方法可通过中缀表示法调用。infix修饰方法只能有一个参数。
fun main(){
var applePack = ApplePack(1.2)
println(applePack.toString())
var apple = Apple(2.4)
println(apple.toString())
var otherApple = Apple(1.1)
println(apple.add(otherApple).toString())
println(apple.drop(otherApple).toString())
val ap = apple add Apple(1.1)
println(ap)
var dp = apple drop Apple(1.1)
println(dp)
}
class ApplePack(weight:Double){
var weight = weight
override fun toString(): String {
return "ApplePack[weight=${this.weight}]"
}
}
class Apple(weight: Double){
var weight = weight
override fun toString(): String {
return "Apple[weight=${this.weight}]"
}
infix fun add(other:Apple):ApplePack{
return ApplePack(this.weight+other.weight)
}
infix fun drop(other: Apple):Apple{
this.weight -= other.weight
return this
}
}
- 类的componentN方法(解构) 类似js原理。从一个对象一次性解析出多个属性给不通的变量。Map中的(key,value)便利使用这个方式。 希望解析多少个变量,那么就需要在类中定义多少个componentN方法。如果有不希望要的属性,使用"_"进行忽略。
Map中for((key,value) in map)因为Map包含一个operator修饰的iterator()方法,且该方法返回Iterator<Map<K,V>>对象.Iterator代表了可迭代的对象,它的泛型参数代表了被迭代的元素类型——Map.Entry<K,V>(Entry是Map的嵌套类),而Map.Entry则定义了如下两个方法:(我没找到)
operator fun <K,V> Map.Entry<K,V>.component1() = getKey()
operator fun <K,V> Map.Entry<K,V>.component2() = getValue()
fun main(){
var (name,pass) = User("张三","abcd",20)
println("结果为:name=$name,pass=$pass")
var (_,e,f)= User("张三","abcd",20)
println("结果为:pass=$e,age = $f")
}
class User(name:String,pass:String,age:Int){
var name = name
var pass = pass
var age = age
operator fun component1():String{
return this.name
}
operator fun component2():String{
return this.pass
}
operator fun component3():Int{
return this.age
}
}
-
数据类
为了简化解构的实现,Kotlin提供了一种特殊的类:数据类。数据类专门用于封装数据。
- 数据类需要data修饰。
- 主构造器至少需要有一个参数。
- 主构造器的所有参数需要用val或者var声明为属性。
- 数据类不能用abstract、open、sealed修饰,也不能定义成内部类。
定义数据类后,系统自动会为类生成:
- 生成equals()/hashCode()方法
- 自动重写toString()方法。
- 为每个属性自动生成operator修饰的componentN()方法。
- 生成copy方法,用于完成对象复制
-
延迟初始化属性 使用lateinit修饰符来解决属性的延迟初始化。
- 只能修饰在类体重声明的可变属性,使用val声明的属性不行,在主构造器中声明的也不行。
- 不能有自定义的getter或setter方法。
- 必须是非空类型。
- 不能是原生类型,即java的8种基本类型对应的类型
-
构造器
kotlin允许主构造器上声明属性,直接在参数前使用var或者val。如果主构造器的所有参数都有默认值,程序能以构造参数的默认值来调用该构造器。
初始化代码块中的数据,在编译后会添加到已有的所有构造器中
-
类的继承
继承是面向对象的三大特征之一,也是实现软件复用的重要手段。kt继承是单继承,每个子类最多只有一个直接父类。从子类的角度来看,子类扩展了父类;从父类的角度来看,父类派生出了子类。扩展和派生所描述的是同一个动作,只是观察的角度不同而已。
如果定义一个类并未显示指定这个类的直接父类,则这个类默认扩展Any类。Any类不是java.lang.Object类。它只有equals()、hashcode()、toString()这3个方法。kt默认使用final修饰类。为类让一个类能派生子类,需要使用open修饰该类。
-
类的方法重写
当子类有多个超类(一个直接父类和多个接口)方法名一样,需要使用super<类名>.方法名 来调用执行父类哪个方法。
fun main(){ var b = B() b.test() b.play() } open class SuperT{ open var a:String = "SuperT-->a" open fun play(){ println("SuperT play") } fun test(){ println("SuperT test") } // private fun test(){ //当父类方法私有,则子类必须重写接口中的方法。当非私有,该方法默认继承到子类,也相当于重写了接口中的同名方法 // println("SuperT test") // } } interface SuperB{ var a: String fun play(){ println("SuperB play") } fun test() } class B:SuperT(),SuperB{ // override fun test() { // println("SuperB test") // } override fun play() { // super<SuperT>.play() //指定调用哪个父类方法 // super<SuperB>.play() println("B中的play"); //当不调用父类方法。执行后输出打印结果 B中的play } }