【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类
来源:互联网 发布:金域名都公寓价格 编辑:程序博客网 时间:2024/06/02 02:23
简介
本篇博客主要是介绍Kotlin语法中的【类的覆盖属性和方法以及抽象类】相关的知识,帮助各位更快的掌握Kotlin,如果有疏漏或者错误,请在留言中指正,谢谢。 系列汇总地址
上一篇博客中我们详细介绍了类的继承和构造,下面我们来讲一下,在继承时如何覆盖方法。
覆盖方法
我们先看一下如何去写,例子如下:
// 父类,使用open关键词open class TestB { open fun test() { //需要被重写的方法需要使用open修饰 }}//子类class TestA() : TestB() { override fun test() {//重写的方法需要使用override super.test() }}
方法和类一样,默认是final的禁止重写的,所以必须加上open
修饰,而重写的方法也必须加上override
,否则子类不允许相同签名的函数。
还有一点是需要注意的,默认override
的函数是open
的,如果你想再次限制它被覆盖,可以使用final
修饰,代码如下:
//子类class TestA() : TestB() { final override fun test() {//重写的方法需要使用override,使用了final,后续无法覆盖 super.test() }}
覆盖属性
我们先看一下如何去写,例子如下:
//父类open class TestB { open var x: Int? = null //属性x get() {//重写了get方法,此处后面详解 field = 34 return field }}class TestA() : TestB() { override var x: Int?=null //它覆盖对应属性后,对应的方法也被覆盖}
对于Kotlin中的属性都有默认的get、set方法,当然也可以重写,比如上面的TestB
的x的属性的get
方法被重写了。但是TestA
覆盖属性后,TestB
中定义的get
方法对其无效,举例如下,便于理解其含义:
var a = TestA() println(a.x) var b=TestB() println(b.x)
输出结果:
null //说明TestB的get方法对TestA类无效34 //说明TestB的get方法对TestB类有效
注意:如果原类型为var
,则覆盖类型可以为var
,且不可以是val
,如果原类型是val
,覆盖类型可以是val
,也可以是var
多实现
在Kotlin中,对于继承来说,如果一个类从它的直接超类继承相同成员的多个实现,它必须覆盖这个成员并提供自己的实现。为了表达采用从哪个超类型继承实现,我们使用super<父类名>
,下面举例说明:
//首先声明一个类open class TestB { open var x: Int? = null get() { field = 34 return field } open fun test() { //此处有一个可以覆盖的方法test() }}
//声明一个接口interface TestC { //这个是接口的声明方式 var x: Int? //声明了一个抽象字段,实现类必须覆盖此属性 fun test() { //声明了一个方法,这个是特殊的,可以有实现方法 print("d") } fun test2() //这个是和java一致的抽象方法}
此处需要注意此处的接口是可以实现具体的方法的
//实现类TestAclass TestA() : TestC, TestB() { override fun test2() {//对于一般的抽象方法等同于java中,必须实现,否则声明成抽象类 } override fun test() {//此处必须写,因为test有两种不同实现 super<TestC>.test() super<TestB>.test() //上面两个都可不写,也可以都写,类似于super.method } override var x: Int? = null //对于字段没影响,因为接口的属性不允许赋值,}
我们总结一波:
- 首先继承
TestB
、TestC
是正常的 - 由于
TestB
、TestC
内都有test
方法,所以TestC
必须实现test
方法 - 在子类
TestC
中使用super<TestB>.test()
或者super<TestC>.test()
来调用父类的实现
上面我们说的是方法,仔细的话,我们还能看到接口还有属性的定义,对于TestB
和TestC
都有x
字段,TestA
中进行重写的话,get/set都会被覆盖,所以不会出现上面方法的问题
还需要注意,看一下代码
open class TestB {//类的一个成员变量 open var x: Int? = null}interface TestC { //这个是接口的声明方式 var x: Int? //声明了一个抽象字段,实现类必须覆盖此属性}//实现类class TestA() : TestC, TestB() {}
我们总结一波:
- 对于接口来说,他的方法默认是抽象的,除非自己实现了
- 对于接口的成员变量也是一样的,也是默认抽象的,子类必须覆盖
- 但凡事都有例外,对于上面的实现中,我们并没覆盖
x
,但仍然正确是,因为,接口只是约束作用,因为TestA
继承了TestB
,也就有了X
,字段,而接口也就是约束必须有该字段即可,所以,上面的实现也是允许的
抽象类
类和类中的某些成员可以声明成abstract
,抽象成员在本类中可以不去实现,需要注意的是我们不需要用open标注抽象类或者函数,更有趣的是看如下实现:
//开放的类和方法open class A{ open fun test(){ }}//抽象类abstract class B : A() { abstract override fun test() //抽象方法覆盖开放方法}
我们可以用一个抽象成员去覆盖一个非抽象的开放成员
伴生对象
与java不同,Kotlin没有静态方法,官方建议使用包级函数,可以使用如下两种方式来实现类似静态类、静态方法的方式
第一种:
object StaticDemo{ fun test(){ print("") }}
使用方法如下:
StaticDemo.test()
第二种:
class Demo { companion object {//声明在内部的,类似静态方法,可以使用 类名.方法名 fun test() { print("") } } fun test2() { //test2在外部,必须实例化后才可调用 }}
使用方法:
Demo.test()
下面我们总结一波:
无论方法还是类除了抽象类、抽象方法、接口、接口方法外,其他的继承都需要写
open
,重写的成员变量和方法需要override
与java不同,Kotlin中的接口可以自己实现方法,从而导致了出现多实现的问题,出现多实现的,继承的子类需要重写对应的方法,然后决定是否或者调用哪个父类的方法。
总结
至此已经学完了Kotlin的【类的覆盖属性和方法以及抽象类】相关的知识,多回顾多思考,继续后续内容。
- 【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类
- 【Kotlin从入门到深坑】之类的属性和字段
- 【Kotlin从入门到深坑】之类的属性和字段
- 【kotlin从入门到深坑】之类和继承
- 【Kotlin从入门到深坑】之返回和跳转
- 【kotlin从入门到深坑】系列目录
- 【kotlin从入门到深坑】之语句
- 【Kotlin从入门到深坑】之基础类型
- 【Intellij Idea 插件从入门到深坑】基础的AnAction
- Kotlin编程之类的属性
- JavaScript面向对象之类方法和类属性的定义
- kotlin(3):类和对象以及其他的概念属性
- 【Intellij Idea 插件从入门到深坑】系列目录
- kotlin开发Android入门篇五方法以及属性的拓展
- Kotlin从入门到精通
- Kotlin 从学习到 Android 第七章 属性和字段
- PHP入门(8) 面向对象(1) 方法和属性的覆盖 访问父类
- C#的抽象类和方法,重载,覆盖,隐藏
- Jsoup使用总结
- 编译内核错误:"mkimage" command not found
- pat-a1064. Complete Binary Search Tree (30)
- 通讯录小感想(1)
- 《数据结构学习与实验指导》2-5:求集合数据的均方差
- 【Kotlin从入门到深坑】之类的覆盖属性和方法以及抽象类
- C语言学习
- H264 术语
- 是热爱不是质疑
- Mybatis 一对多(OneToOne)关系映射
- git分支管理
- Kotlin单例模式(带参数和不带参数)
- keras中Convolution1D的使用(CNN情感分析yoom例子四)
- Epoll介绍和使用