1、继承
和Java一样,Kotlin继承也是***单继承***,每个子类最多只有一个直接父类
语法格式:
[修饰符] class 子类名:父类名{
}
- 定义一个Kotlin类没有显示指定父类,默认扩展Any类。Any类是所有类的父类(要么直接父类要么间接父类);Any类不是java.lang.Object类
- Kotlin的类默认时final修饰的,即不能派生子类,为了让其类可以派生子类,可以使用“open”修饰符修饰类
- Kotlin默认所有的方法添加final修饰符,阻止该方法被重写,添加open关键字阻止Kotlin自
动添加final修饰符
open修饰符用于取消自动添加的final修饰符
###1.1、 委托父类构造器 ###
在Java中子类构造器调用父类构造器:
- 子类构造器执行第一行使用“super(参数)”显示调用父类构造器
- 子类构造器第一行使用this(参数)调用本类中重载构造器,调用的重载构造器最终还是要调用父类构造器
- 子类构造器既没有"super(参数)"也没有"this(参数)"调用,系统将会在执行子构造器之前,隐式调用父类无参构造器;
Kotlin调用父类构造器:
第一种情况:子类有主构造器
前面我们说了,次构造器总是会调用主构造器.利用主构造器最终调用父类构造器
class BaseClass{
var name:String
constructor(name:String){
this.name=name
}
}
-
子类没有任何构造器(主构造器、次构造器),系统会为类默认生成一个无参主构造器
class SubClass:baseClass(“leslie”){}
-
子类显示声明了主构造器
class SubClass(name:String):BaseClass(name){
扫描二维码关注公众号,回复: 3493787 查看本文章}
第二种情况:只有次构造器,没有声明主构造器
- 次构造器中显示使用"this(参数)"调用本类中另一重载构造器,另一个重载构造器最终还是要调用父类构造器
- 子类显示调用"super(参数)"委托调用父类构造器,系统将根据参数调用父类对应的构造器
- 子类构造器既没有显示调用“super(参数)”,也没有显示调用"this(参数)",系统将会在执行子类构造器执念,隐式调用父类无参构造器
Kotlin调用父类构造器和Java区别:Java是现在构造器体内的,而Kotlin是写在构造器声明中
可以得出一个结论:在初始化子类对象时,父类构造器总是在子类构造器之前执行,以此类推…即Any类构造器总是会先执行;
1.2 重写父类方法
- Kotlin默认所有的方法添加final修饰符,阻止该方法被重写,添加open关键字阻止Kotlin自
动添加final修饰符 - 子类重写父类方法:子类中重写的方法必须使用override修饰符,其次父类必须使用open修饰符,父类才能被继承,最后父类中被重写的方法必须也使用open修饰符
重写遵循的原则:两同两小一同
两同:方法名、参数列表必须相同(参数个数、参数类型)
两小:子类方法返回值类型必须父类方法返回值类型小或者相等、子类方法抛出的异常必须必父类方法抛出的异常小或者相等
一大:子类方法访问权限必须比父类方法访问权限相等或者更大
子类重写父类方法后,子类对象将无法访问父类中被覆盖的方法,但是可以***在子类的所有方法中调用父类被覆盖的方法(super.被重写方法())即在子类内部被覆盖的方法任然是可见的***;
如果父类的方法是private访问修饰符,该方法不能重写,即使子类中有一个和父类同样的方法,也不是重写,而且子类同名(相同方法名、相同形参列表、相同返回值类型)的这个方法不能使用override修饰符,因为不是方法重写;
如:
open class Base {
private fun test() {
}
}
class Sub:Base(){
fun test(){
}
}
1.3、属性重写
要求:
- 父类被重写的属性必须使用open修饰符
- 子类的属性类型与父类属性类型要兼容
- 子类重写属性访问权限要大于或者等于父类属性权限;
- 只读属性可以被读写属性重写,读写属性不能被只读属性重写
父类中private修饰的属性,只能在该类内部访问,不能别子类重写
1.4 强制重写
这种情况比较特殊:子类同时继承类和实现了接口(父类和接口中存在同名的成员(属性、方法)),Kotlin就要求子类必须重写该成员。子类中使用"super<超类型>.重写方法()"来调用超类方法
open class Animal{
open val name:String="动物"
public open fun say(){
println("动物叫")
}
}
interface IAnimal{
val name:String
fun say(){
println("接口-动物叫声")
}
}
class Cat:Animal,IAnimal{
constructor() : super()
override val name: String
get() = super<Animal>.name
override fun say() {
super<Animal>.say()
super<IAnimal>.say()
}
}
注意:接口中的方法默认有open修饰符;关于接口后面会详细讲解
2.多态
和Java一样,唯一需要不同的是:在Java中,属性不具有多态,而kotlin中的属性和方法一样具有多态
如Kotlin:
var sub:Base=Sub();
pritnln("${sub.age}")//将输出子类中重写的属性值