与Java类似,在Kotlin中,类通过class关键字创建
1 主构造函数 和 次构造函数
1.1 主构造函数
在Kotlin类中,可以有一个主构造函数以及1个或者多个次构造函数;
主构造函数在声明类的时候定义,就是类名后的 + 花括号{ }内的主体
class Person constructor (var name:String){
}
这个Person类名后边的一部分就是主构造函数,在没有访问修饰符(public private…)或者注解修饰的情况下,可以把constructor去掉
class Person public constructor (var name:String){
}
通过public修饰后,constructor就必须加上
主构造函数中不能存在任何代码,所有初始化的操作可以放在init中执行,主构造函数中可以有多个init,按照声明的顺序执行。
class Person public constructor (var name:String){
//属性初始化器
val printName = "当前输入的$name".also { s-> println(s) }
init {
println("第一个init代码块")
}
init {
println("第二个init代码块")
}
open fun draw(){
println("draw 方法")
}
}
创建对象
var person = Person("hello")
println(person.name)
打印输出:
当前输入的hello
第一个init代码块
第二个init代码块
1.2 次构造函数
次构造函数,通常使用constructor关键字创建,如果当前类存在主构造函数,那么次构造函数需要委托给主构造函数,通过this关键字即可
class Student{
constructor(name: String){
println("次级构造函数")
}
}
因为Student没有主构造函数,因此不需要委托给主构造函数
class Student(var name: String){
constructor(name: String,age:Int) : this(name) {
println("次级构造函数")
}
}
如果存在主构造函数,那么就需要通过this关键字委托主构造函数,类似于重载
class Student(var name: String){
val initPrimary = "主构造函数$name".also { s-> print(s) }
init {
println("主构造函数初始化")
}
constructor(name: String,age:Int) : this(name) {
println("次级构造函数")
}
}
调用
var student = Student("kobe", 41)
在通过次级构造函数创建对象时,首先会执行主构造函数的属性初始化器和init代码块,执行完成之后,才会执行次构造函数的内部代码
2 类的继承
2.1 继承
在Kotlin中,所有的类都有一个共同的超类,类似于Java中的Object
默认情况下,类是不能被继承的;如果该类能够被继承,那么需要使用open关键字修饰
class Student(name: String) : Person(name){
constructor(name: String,age :Int) : this(name){
print("Student的次级构造函数")
}
}
如果派生类有一个主构造函数,那么基类必须使用派生类的参数就地初始化,在初始化时,首先初始化主构造函数的init代码块,然后再执行子类的主构造函数 + 次构造函数;要避免在基类的构造函数或者init块中使用open关键字
class Student : Person {
constructor(name: String) : super(name){
print("派生类次级构造函数")
}
override fun draw() {
super.draw()
}
}
如果派生类没有主构造函数,需要通过super关键字在次构造函数中初始化基类
2.2 重写方法
Java中,子类重写父类的方法;Kotlin中,想要重写父类的方法,需要父类的方法为开放类型
final override fun draw() {
super.draw()
}
如果想要禁止被再次覆盖,可以通过final关键字修饰;
对于属性的覆盖,同样可以通过override关键字实现
2.3 内部类访问外部类的超类
class Student : Person {
constructor(name: String) : super(name){
print("派生类次级构造函数")
}
final override fun draw() {
super.draw()
}
val ss:String get() = super.printName
inner class Ming{
fun outerMethod(){
super@Student.draw()
}
}
}
Ming是Student的一个内部类,如果Ming想要访问Person中的draw方法,那么就可以通过super@OuterClass.SuperMethod的方式调用超类的方法
调用
var ming = Student("name").Ming()
ming.outerMethod()
2.4 覆盖规则
如果一个类从它的直接超类继承相同成员的多个实现, 它必须覆盖这个成员并提供其自己的实现;
2.5 抽象类
同Java一样,抽象类使用abstract关键字修饰,可以有构造函数但不能具体实现某个方法
interface Car{
fun draw()
}
abstract class Benz : Car{
abstract override fun draw()
}
3 属性和字段
3.1 属性的声明
通过var声明可变的属性,对应get和set方法,val定义的变量为只读,只能通过get获取
3.2 编译器常量
如果当前属性在编译器已经确定,可以使用const修饰,常见的就是修饰String字符串
3.3 延迟初始化
在Kotlin中,属性声明为非空的对象必须要初始化,但是如果不想立即初始化,可以使用lateinit关键字稍后初始化,类似于Dart中的late
lateinit var age:String
lateinit var person:Person
lateinit var number:Int
但是其中遇到的lateinit是不能作用在Int类型,会报错,这种情况可以使用Number代替Int
lateinit var number:Number
public fun set(i : Int) {
number = i
}