kotlin类和对象
一:类
kotlin使用class关键字来声明类
class Invoice{}
class Empty //如果类没有实体可以省略{ }
二:构造函数
kotlin中一个类可以有一个主构造函数以及一个或多个次构造函数。
1.1:主构造函数
它跟在类名(与可选的类型参数)后,如果没有注解或可见性修饰符可以省略constructor关键字
class Person constructor(name: String) {}
class Person (name: String ){} //这两个声明是一样的
主构造函数不能包含任何代码块, 初始化的代码可以放到以init关键字为前缀的代码块中。
class Person (val name: String) {
val s = "name $name".also(:: println)
init {
println("init name : $name")
}
val tian = "songtao $name".also(::println)
}
注意:主构造函数中的参数可以在初始化块中使用,也可以在类体内声明的属性初始化器中使用。
在类实例化期间,初始化块和属性初始化器按住在类中编码的顺序执行。
1.2:次构造函数
类也可以声明前缀有constructor的次构造函数,如果一个类中有主构造函数那么每一个次构造函数都需要
委托给主构造函数,可以直接委托也可以通过别的次构造函数委托,委托同类构造函数使用this关键字
class Person (val name: String) {
val s = "name $name".also(:: println)
init {
println("init name : $name")
}
val tian = "tian name: $name".also(:: println)
constructor(name: String, age: Int): this(name) {
}
}
注意:初始化块中的代码实际会作为主构造函数的一部分,委托给主构造函数实际上会作为次构造函数的第一条代码执行。因此初始化块都是执行在次构造函数之前,即使没有主构造函数这种委托也会隐式存在。
如果一个类没有任何主次构造函数,它会生成一个不带参数的主构造函数,如果你想你的类没有一个公共的主构造函数,可以用限制符声明它的非公共主构造函数
class Tian private constructor(){}
三:创建类的实例
kotlin中没有Java的new关键字,实例化类像普通函数一样调用构造函数
val person = Person("tian")
四:类成员
类的成员包括
- 构造函数和初始化块
- 函数
- 属性
- 嵌套类和内部类
- 对象声明
五:继承
kotlin中所有的类都有一个共同的超类Any, 和Java中的object一致,没有超类声明的类Any就是它的默认超类,要声明一个超类,我们把类型放到类头的冒号后. kotlin力求显示清晰,与Java不同,kotlin对于公开的超类和可重写的函数都需要用时open关键字来显示指定公开,类似java中的public。
open class Person
class Man : Person
open class Woman(name:String): Person()
class Student(name:String): Woman(name)
class MyView: View{
constructor(context: Context): super(context)
constructor(context: Context, attrs: AttributeSet): super(context, attrs)
}
注意:如上,如果子类有主构造函数,那么超类就可以直接用子类主构造函数中的参数直接初始化。如果类没有主构造函数,那么每个次构造函数都需要使用super关键字来初始化超类,也可以委托给其他次构造函数,不同次构造函数也可以调用不同的超类次构造函数。
六:覆盖方法
可以被子类覆盖的方法为公开方法,也需要使用open显示指定
open class Person{
open fun open(){
println("open")
}
fun unOpen(){ //没有open显示指定,这个函数不能被重写覆盖,
println("unOpen")
}
}
class Man : Person(){
override fun open() { //这里必须使用override关键字来修饰,
super.open()
}
final override fun open(){ //子类不可在覆盖
super.open()
}
}
注意:不可覆盖的方法在子类和超类中不可有相同函数名的函数,也就是Man类中不可定义超类的unOpen函数。override本身就是open的,Man的子类也可覆盖open函数,如果不想覆盖就使用final关键字修饰。
七:覆盖属性
覆盖属性和覆盖方法类似。
八:调用超类的实现
1.1:子类调用超类函数使用super关键字,
class Man : Person(){
override fun open() { //这里必须使用override关键字来修饰,
super.open()
}
}
1.2:子类内部类调用子类超类。
内部类调用外部类的超类可以使用super关键字的限定名来实现,super@outer
class Man: Person(){
override fun open(){
super.open()
}
inner class student{
fun g(){
super@Man.open() //这里使用@标记super为谁的super,这里这个关键字super是Man的super,
//所以这个super@Man.open()调用的是Man的超类Person的open函数。
}
}
}
1.3:多超类情况
如果一个类从它的直接超类继承相同成员的多个实现,它必须覆盖(重写)这个成员并自己实现,为了表明
采用的的那个超类继承的实现,可以使用super<超类名>来限定是那个超类。
open class A {
open fun f(){}
}
interface B {
fun f(){}
}
class C: A(), B {
override fun f() {
super<A>.f() //super后跟<超类名>来标记调用的是那个超类的函数
super<B>.f()
}
}
九:抽象类
kotlin中抽象类和Java中的类似,抽象类中的抽象函数可以没有函数体。抽象函数自带open不用显示声明
open class A{
open fun f(){}
}
abstract class B: A() {
override abstract fun f()
}