当前位置:网站首页>【Kotlin学习】类、对象和接口——定义类继承结构
【Kotlin学习】类、对象和接口——定义类继承结构
2022-07-03 08:59:00 【安卓老猴子】
定义类继承结构
kotlin中的接口
下图声明了一个拥有名为click的单抽象方法的接口,所有实现该接口的非抽象类都要提供这一方法的实现

kotlin使用冒号代替了extends和implements关键字,和java一样,一个类可实现多个接口但只能继承一个类

在kotlin中使用override修饰符是强制要求的,这会避免先写出实现方法在添加抽象方法造成的意外重写
接口的方法可以有一个默认实现,在Java8中需要你在这样的实现上标注default关键字,而kotlin没有特殊的注解,只需要提供一个方法体

现在再定义一个Focusable接口,其中同样实现了一个showOff方法
当你的类实现这两个接口时,不会使用任何一个实现,编译器会要求你提供你自己的实现

修改MyButton类如下

要调用一个继承的实现,可以使用super关键字,但是选择一个特定实现的语法是不同的,在java中是Clickable.super.showOff(),而在kotlin中是super< Clickable>.showOff()
在Java中实现包含方法体的接口
Kotlin1.0是以Java 6为目标设计的,并不支持接口中的默认方法,因此它会把每个带默认方法的接口编译成一个普通接口和一个将方法体作为静态函数的类的结合体。
open、final、abstract修饰符:默认为final
在Java中允许你创建任意类的子类并重写任意方法,除非显式调用了final关键字进行标注。对基类进行修改会导致子类不正确的行为,这就是所谓的脆弱的基类问题,因为基类代码的修改不再符合在其子类中的假设。基类的任何修改都有可能导致子类出现与其之外的行为改变。
在java中类和方法默认都是open的,在kotlin中类和方法默认都是final的。
如果你想允许创建一个类的子类,则要使用open修饰符来标示这个类,还要给每一个可以重写的属性和方法添加open修饰符

如果你重写了一个基类或者接口的成员,重写了的成员同样默认是open的,如果你想阻止你的类的子类重写你的实现,可以显式将重写的成员标为final

open类和智能转换
类默认final使得在大量场景中的智能转换成为可能,我们之前提到智能转换只能在进行类型检查后没有改变过的变量上起作用,对于一个类来说,这意味着智能转换只能在val类型并且没有自定义访问器的类属性上使用。这个前提意味这属性必须是final的,否则入股一个子类可以重写属性并定义一个自定义的访问器将会打破智能转换的关键前提
在kotlin中,可以将一个类声明为abstruct的,这种类不能被实例化。它通常包含一些没有实现并且必须在子类重写的抽象成员。抽象成员始终是open的,所以不需要显式使用open

| 类中访问修饰符 | 相关成员 | 评注 |
|---|---|---|
| final | 不能被重写 | 类中成员默认使用 |
| open | 可以被重写 | 需要明确表明 |
| abstruct | 必须被重写 | 只能在抽象类中使用,抽象成员不能有实现 |
| override | 重写父类或接口中的成员 | 如果没有用final表明。重写的成员默认是开放的 |
可见性修饰符:默认为public
kotlin中和java几乎一样,但是默认情况不一样,kotlin默认是public。
而且提供了一个新修饰符:internal(只在模块内部可见),一个模块就是一组一起编译的kotlin文件,有可能是一个IDEA模块、一组使用调用Ant任务进行编译的文件等等。
kotlin还允许在顶层声明中使用private,包括类、函数、属性,这些声明就会只在声明它们的文件中可见
| 可见性修饰符 | 类成员 | 顶层声明 |
|---|---|---|
| public | 所有地方可见 | 所有地方可见 |
| internal | 模块中可见 | 模块中可见 |
| protected | 子类中可见 | 无 |
| private | 类中可见 | 文件中可见 |

kotlin禁止从public函数giveSpeech去引用低可见的类型TalkativeButton(internal)。通用规则:类的基础类型和类型参数列表中用到的所有类,或者函数的签名都有与这个类或者函数本身相同的可见性。
注意protected修饰符在java和kotlin的不同,在java中可以从同一个包中访问protected成员,但kotlin不允许,在kotlin中只允许其成员在类和它的子类中可见
注意类的扩展函数不能访问它的private和protected成员
kotlin的可见性修饰符和java
kotlin的public、protected、private修饰符在编译成java字节码时会被保留。唯一的例外是private类:这种情况会被编译成包私有声明。
一个模块通常会由多个包组成,并且不同模块可能会包含来自同一个包的声明,因此internal修饰符在字节码中会变成public,这就解释了为什么有时能从java代码中访问一些你不能从kotlin中访问的东西
类的internal成员名字会被破坏
在kotlin中一个外部类不能看到其内部/嵌套类中的private成员
内部类和嵌套类:默认是嵌套类
在kotlin中可以在另一个类中声明一个类,这样做在封装一个辅助类或者把一些代码放到靠近它被使用的地方时非常有用。但区别于Java,kotlin的嵌套类不能访问外部类的实例,除非你特别地作出了要求。
实例 声明一个包含可序列化状态的视图



可以看到我们试图返回一个实现了State接口的ButonState,在kotlin中可行,在java中这样的写法会报错,因为在java中ButtonState类隐式地存储了它的外部MyButton的引用,而MyButton是不能被序列化的,它的引用破坏了ButtonState的序列化。要修复它需要声明ButtonState类为static,这个嵌套类就会删除包围它的类的隐式引用。kotlin中没有显式修饰符的嵌套类和java中的static嵌套类是一样的。要把它变成一个内部类来持有一个外部类的引用的话要使用inner修饰符
| 类A在另一个类B声明 | 在Java中 | 在Kotlin中 |
|---|---|---|
| 嵌套类(不存储外部类的引用) | static class A | class A |
| 内部类(存储外部类的引用) | class A | inner class A |
在kotlin中引用外部类实例的语法也和java不同,需要用[email protected]从Inner类访问Outer类

密封类:定义受限的类继承结构
回顾在kotlin基础篇章中的例子

在when表达式中处理所有可能的子类固然方便,但是必须提供一个else分支来处理没有任何其他分支能匹配的情况。总是不得不添加一个默认分支很不方便,更重要的是如果你添加了一个新的子类,编译器并不能发现有地方改变了,如果你忘记添加新分支那么就会有bug。
kotlin为此提供了一个解决方案:sealed类。
为父类添加sealed修饰符,对可能创建的子类做出严格的限制,所有的直接子类必须嵌套在父类中

密封类是不能在类外部拥有子类的,如果你在when表达式中处理所有sealed类的子类,就不需要再提供默认分支。sealed修饰符隐含的这个类是一个open类,不再需要显式地添加open修饰符。
我们不能声明sealed接口,因为编译器不能保证任何人都不能在java代码中实现这个接口
在kotlin1.0中,sealed功能是相当严格的,所有子类必须是嵌套地,且子类不能创建为data类。1.1中解除了这些限制并允许在同一文件地任何位置定义sealed类的子类
边栏推荐
- Find the combination number acwing 886 Find the combination number II
- Wonderful review | i/o extended 2022 activity dry goods sharing
- What are the stages of traditional enterprise digital transformation?
- Install third-party libraries such as Jieba under Anaconda pytorch
- Debug debugging - Visual Studio 2022
- 干货!零售业智能化管理会遇到哪些问题?看懂这篇文章就够了
- Common DOS commands
- 教育信息化步入2.0,看看JNPF如何帮助教师减负,提高效率?
- 【点云处理之论文狂读经典版14】—— Dynamic Graph CNN for Learning on Point Clouds
- Recommend a low code open source project of yyds
猜你喜欢

【点云处理之论文狂读前沿版9】—Advanced Feature Learning on Point Clouds using Multi-resolution Features and Learni

With low code prospect, jnpf is flexible and easy to use, and uses intelligence to define a new office mode

How to use Jupiter notebook

即时通讯IM,是时代进步的逆流?看看JNPF怎么说

一个优秀速开发框架是什么样的?

On February 14, 2022, learn the imitation Niuke project - develop the registration function

求组合数 AcWing 885. 求组合数 I

Binary tree sorting (C language, int type)

LeetCode 515. 在每个树行中找最大值

2022-2-13 learn the imitation Niuke project - Project debugging skills
随机推荐
Uc/os self-study from 0
Discussion on enterprise informatization construction
LeetCode 871. Minimum refueling times
Facial expression recognition based on pytorch convolution -- graduation project
Solve POM in idea Comment top line problem in XML file
我們有個共同的名字,XX工
网络安全必会的基础知识
Introduction to the usage of getopts in shell
2022-2-13 learn the imitation Niuke project - Project debugging skills
Memory search acwing 901 skiing
AcWing 785. 快速排序(模板)
Using DLV to analyze the high CPU consumption of golang process
低代码起势,这款信息管理系统开发神器,你值得拥有!
[point cloud processing paper crazy reading classic version 7] - dynamic edge conditioned filters in revolutionary neural networks on Graphs
C language programming specification
状态压缩DP AcWing 91. 最短Hamilton路径
Excel is not as good as jnpf form for 3 minutes in an hour. Leaders must praise it when making reports like this!
With low code prospect, jnpf is flexible and easy to use, and uses intelligence to define a new office mode
How to use Jupiter notebook
LeetCode 30. 串联所有单词的子串