类的声明
类声明由类名、类头(指定其类型参数、主构造函数等)和由⼤括号包围的类体构成。类头和类体都是可选的
定义一个最简单的类
class A
这样就定义了最简单的一个类了,什么都没有的类,没有类头和类体。(没有类体,可以省略花括号)
接下来定义一个正常的类:
class Person public constructor(name: String,age: Int)/*主构造函数,和它参数*/{
var name:String //属性
var age :Int
init { //初始化器,主构造函数的函数体,能使用主构造函数的参数
= name
= age
}
//成员函数
fun say(){
println("I am ${name} and I was ${age} years old")
}
}
但是实际上,上面的类定义太复杂了,因为:
1. 除非构造函数有明确必要私有,一般情况,默认为公有的
2. 属性可以写在主构造函数中,除非有一些属性在创建时不要初始化,不要初始化的属相或者延迟初始化的属性写在可以写在类里
3. init 只是主构造函数的方法体,没有特殊要求也可以省略
接下来简化的类的写法如下:
class Person(var name: String ,var age: Int){
//成员函数
fun say(){
println("I am ${name} and I was ${age} years old")
}
}
类中属性初始化问题
注意类中的属性不像Java那样声明了就会有默认值,我们可以不初始化它
kotlin中,类的属性必须要初始化或者延迟初始化:
我们先不管延迟初始化,先看看我们初始化的方式有几种
1 . 定义时直接给它赋予初始值
class User{
//属性定义方式1,直接给它初值
var name:String = ""
var age:Int =0
}
2 . 使用init块初始化:init相当于主构造函数的函数体,所以能用主构造函数的参数
class User(name: String){
//属性初始化方式2,使用init
var name:String
var age:Int
init {
this.name = name
this.age = 0
}
}
3 . 直接调用主构造函数的参数
class Customer(name: String) {
val customerKey = ()
}
4 . 直接把属性定义在主构造函数中,这样我们创建对象的时候就直接把属性初始化了
class User(var name: String,var age: Int)
5 . 延迟初始化
延迟初始化可以把属性的初始化推迟到要访问这个属性之前,但是访问之前还没有初始化就会抛出 的异常,不过要注意的是延迟初始化的属性不能是原生类型(Byte,Short,Int,Long,Float,Double,char,Boolean)八种,像String类型就可以延迟初始化
class User(var name: String,var age: Int){
lateinit var gender :String
}
fun main(args: Array<String>) {
var user = User("huahua",11)
//如果在要访问这个属性之前还不初始化,那么就会抛出异常
//所以访问之前一定要初始化延迟初始化属性
println()
}
关于属性特别注意的是:和Java不同,不要轻易的用private修饰属性,它会是属性的setter和getter也私有化,要使属性能够访问到,尽量不要加权限修饰符,这一点一定要从Java的封装性中走出来!!!!
另外:要注意属性声明的是var还是val,var是可变属性,具有getter和setter,val是只读属性,只有getter
构造函数
Kotlin 中的⼀个类可以有⼀个主构造函数和⼀个或多个次构造函数。主构造函数是类头的⼀部分:它跟在类名(和可选的类型参数)后
类也可以声明前缀有 constructor的次构造函数
class User(var name: String){
lateinit var age :String
constructor(name: String,age: String):this(name){ //直接委托主构造函数
}
constructor():this("huahua","11"){ //通过委托另一个构造函数,间接委托主构造函数
}
}
注意:
- 如果主构造函数没有任何注解或者可⻅性修饰符,可以省略这个 constructor 关键字
- 主构造函数不能包含任何的代码。初始化的代码可以放到以 init 关键字作为前缀的初始化块(initializer blocks)中
- 主构造的参数可以在初始化块中使⽤。它们也可以在类体内声明的属性初始化器中使⽤(上面属性初始化已经说过)
- 如果构造函数有注解或可⻅性修饰符,这个 constructor 关键字是必需的,并且这些修饰符在它前⾯
- 如果类有⼀个主构造函数,每个次构造函数需要委托给主构造函数,可以直接委托或者通过别的次构造函数间接委托,委托到同⼀个类的另⼀个构造函。数⽤ this 关键字即可(上面的代码已经说明了委托)
- 如果⼀个⾮抽象类没有声明任何(主或次)构造函数,它会有⼀个⽣成的不带参数的主构造函数。构造函数的可⻅性是 public。如果你不希望你的类有⼀个公有构造函数,你需要声明⼀个带有⾮默认可⻅性的空的主构造函数
- Kotlin在 JVM 上,如果主构造函数的所有的参数都有默认值,编译器会⽣成 ⼀个额外的⽆参构造函数,它将使⽤默认值。这使得 Kotlin 更易于使⽤像 Jackson 或者 JPA 这样的通过⽆参构造函数创建类的实例的库,如下:
- 如果没有声明主构造函数 ,就不用声明委托主构造函数了,其实是默认委托给无参构造函数了
- 如果没有在类名后面声明主构造函数,如果有一个无参的构造函数,那么会被当作主构造函数。
- init块中的代码是在创建对象以定会执行的(这里有像Java的初始化块)
class LL1{
var name:String
init {
println("_主")
= ""
}
constructor(name: String){
=name
}
constructor(){
println("_次")
}
constructor(name: String,age: Int)
}
fun main(args: Array<String>) {
var l = LL1() //因为有默认的主构造函数,所以能这样创建对象
}
class User {
lateinit var name:String
constructor(name: String){
=name
}
init {
println("lala")//调用每个构造方法之前会调用init中的代码
}
constructor(){
println("主")
}
}
创建类的对象
kotlin中并没有new关键字,创建对象是直接调用构造方法
fun main(args: Array<String>) {
var u = User()
}
类的成员
- 构造函数和初始化块
- 函数
- 属性
- 嵌套类和内部类
- 对象声明
这里小编只说了构造函数和初始化块,之后会补上其他成员的文章
结语:
此篇文章,是小编自己测试之后才发表的,所以如果有什么遗漏或者错误,还请大家用于在评论区指正。