你们知道幕后字段吗?(Kotlin中基本类的创建)
# 一、构造函数和初始化块
# 1.初始化块
代码的初始化工作由它负责,在调用主构造函数之前执行,这部分理论上可以进行任何工作,但建议类的初始化赋值可以放在这,其余的最好由其他专门的地方处理,采用init关键字
init{
println("ww cool")
}
2
3
# 2.主构造函数
主构造函数只能由一个,初始化块相当于放在主构造函数的无参函数中,按顺序执行初始化块,这一点和传统的面向对象编程中的主构造函数没有太大的区别。由关键字constructor提供,一般情况省略此关键字
class MyClass (name:String){
}
//或者使用关键字
class MyClass constructor(name:String){
}
2
3
4
5
6
7
8
# 3.次构造函数
同样使用constructor关键字作为函数名,但它不能省略函数名,使用时需要调用主构造函数
class MyClass constructor(name:String){
constructor(name1:String,name2:String):this(name1){
//这部分规则和大多数面向对象的规则差不多
}
}
2
3
4
5
谈谈主构造函数和次构造函数的区别
- 次构造函数可以有多个,而主构造函数只能有一个
- 次构造函数可以包含代码,主构造函数不行
- 次构造函数属性不能用var和val关键字修饰而主构造函数可以
# 4.他们之间的联系
初始化块有多个的情况下,按照声明顺序执行,主构造函数调用之前会执行初始化块,而次构造函数调用之前会先执行主构造函数的初始化块然后再调用主构造函数
//顺序如下
初始化块->主构造函数->次构造函数
2
# 二、属性
# 1.属性的声明
最简单的方式
class MyClass(){
val name:String
}
2
3
此时默认已经帮你创建好了getter和setter,val 类型的只有getter,var类型的两个都有
也可以手动创建getter和setter,如果对它们不满意的话
class MyClass(){
var name:String
get() = "my"
//set等下请看幕后字段
}
2
3
4
5
# 2.避免递归调用的幕后字段
下面这个代码看上去好像没有问题,但事实上它递归调用了属性的get和set方法
class MyClass(){
var name:String
get() = name
set(value){
this.name = value
}
}
2
3
4
5
6
7
执行一下,果然报错了,栈溢出报错
[外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传(img-7dTP9u4S-1639369491606)(C:\Users\y\Desktop\博客\kotlin100天学完\主构造函数、次构造函数、初始化块之间的爱恨情仇(Kotlin中基本类的创建)]\1.jpg)
原因就是递归调用了name这个属性导致的,所以这就要引入一个幕后字段进行调整,便于再setter和getter时替换变量
class MyClass(){
var name:String
get() = field
set(value){
field = value
}
}
2
3
4
5
6
7
这一点和java语言差异比较大,需要注意一下,不过平时基本上不会用到自定义的setter和getter,所以不用这么担心
# 三、常用的类
抽象类
含有抽象方法的类称为抽象类,这一点和java里面很像
内部类
使用inner关键字,可以访问内部类外的属性
class outer{ val name = "ww" inner class inside{ println("my name is $name") } }
1
2
3
4
5
6嵌套类
和内部类很像,但是没有加inner关键字,不能访问外部的变量
class outer{ val name = "ww" class inside{ println("my name is ww") //不能直接调用外部的变量 } }
1
2
3
4
5
6
7枚举类
与传统的java写法相比,由于少了getter和setter,所以代码显得相当简洁,也很容易读懂
enum class Color ( var colorName: String, var number:Int){ Green("绿色",1), Blue("蓝色",2) }
1
2
3
4