Kotlin——抽象类(abstract)、内部类(嵌套类)详解
程序员文章站
2024-02-17 16:31:34
...
目录
一、抽象类
- 我们知道,在实际的开发程序的时候,一般都会写一个基类,封装常用方法、以及处理一些共有的逻辑,但是程序逻辑是根据每个类不同的功能实现不同的代码。而这个所谓的基类,一般都是一个抽象类。不管是
Java
还是Kotlin
,实现其抽象类的作用就在于此。那么什么是抽象类呢,它是怎么定义的,它又要怎么使用呢?
1、抽象类的定义
抽象类,可以理解为类定义了一个模板。所有的子类都是根据这个模板是填充自己的代码。
1.1、关键字
- 声明一个抽象(类或函数)的关键字为:
abstract
其中值得注意的是:抽象可以分为抽象类、抽象函数、抽象属性。而一个抽象类和普通类的区别在于抽象类除了可以有其自己的属性、构造函数、方法等组成部分,还包含了抽象函数以及抽象属性。
例:
abstract class Lanauage{
val TAG = this.javaClass.simpleName // 自身的属性
// 自身的函数
fun test() : Unit{
// exp
}
abstract var name : String // 抽象属性
abstract fun init() // 抽象方法
}
/**
* 抽象类Lanauage的实现类TestAbstarctA
*/
class TestAbstarctA : Lanauage(){
override var name: String
get() = "Kotlin"
set(value) {}
override fun init() {
println("我是$name")
}
}
/**
* 抽象类Lanauage的实现类TestAbstarctB
*/
class TestAbstarctB : Lanauage(){
override var name: String
get() = "Java"
set(value) {}
override fun init() {
println("我是$name")
}
}
fun main(args: Array<String>) {
// val lanauage = Lanauage() 是错误的,因为抽象类不能直接被实例化
val mTestAbstarctA = TestAbstarctA()
val mTestAbstarctB = TestAbstarctB()
println(mTestAbstarctA.name)
mTestAbstarctA.init()
println(mTestAbstarctB.name)
mTestAbstarctB.init()
}
输出结果为:
Kotlin
我是Kotlin
Java
我是Java
1.2、小结
- 抽象类本身具有普通类特性,以及组成部分。不过值得注意的是,抽象类不能直接被实例化
- 其抽象了类的子类必须全部重写带
abstract
修饰的属性和方法。- 抽象成员只有定义,没有实现。都有
abstract
修饰符修饰。- 抽象类是为其子类定义了一个模板。不同是类实现不同的功能
2、抽象类的规则
- 在
Kotlin
中的抽象类在顶层定义的时候只能使用public
可见性修饰符修饰。- 抽象类中可以定义内部抽象类。
- 只能继承一个抽象类。
- 若要实现抽象类的实例化,需要依靠子类采用向上转型的方式处理。
- 抽象类可以继承自一个继承类,即抽象类可以作为子类。不过,抽象类建议不用
open
修饰符修饰,因为可以覆写抽象类的父类的函数。
例:
open class Base{
open fun init(){}
}
abstract class Lanauage : Base(){
val TAG = this.javaClass.simpleName // 自身的属性
// 自身的函数
fun test() : Unit{
// exp
}
abstract var name : String // 抽象属性
abstract override fun init() // 覆写父类的方法
abstract class Name(){} // 嵌套抽象类,可查看第二节中的嵌套类使用
}
fun main(args: Array<String>) {
// 若要实现抽象类的实例化,需要依靠子类采用向上转型的方式处理。
val mLanauage : Lanauage = TestAbstarctB()
}
3、抽象类的实际应用
- 在
Java
的设计模式中,有一种设计模式叫模板设计模式
,其定义为:- 定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
- 通俗点的理解就是 :完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。
Kotlin
和Java
是互通的,说明Kotlin
也是支持这种设计模式的。
如果你对Java
中的模板设计模式不是很了解的,请参见这篇文章
二、内部类(嵌套类)
在实际开发中,用到内部类的地方是很多的。比如说:
- 对于
Android
开发来说,列表适配器(adapter
)中的ViewHolder
类,就是一个内部类。- 根据后台开发人员提供的
json
字符串生成的对象中,也包含另外一个对象,这也是一个内部类。
1、嵌套类
上面提到的两种情况,是在开发中最常见的。当然,说到内部类,就必须世道另一个概念嵌套类,所谓的嵌套类:即指一个类可以嵌套在其他类中。
例:
class Other{ // 外部类
val numOuther = 1
class Nested { // 嵌套类
fun init(){
println("执行了init方法")
}
}
}
fun main(args: Array<String>) {
Other.Nested().init() // 调用格式为:外部类.嵌套类().嵌套类方法/属性
}
输出结果为:
执行了init方法
注意:
- 调用嵌套类的属性或方法的格式为:
外部类.嵌套类().嵌套类方法/属性。在调用的时候嵌套类是需要实例化的
。- 嵌套类不能使用外部类的属性和成员
2、内部类
在上面的例子中讲解了嵌套类的使用,而内部类和嵌套类还是有一定的区别的,而且内部类是有特定的关键字去声明的。
2.1、关键字
声明一个内部类使用
inner
关键字。
声明格式:inner class 类名(参数){}
例:
class Other{ // 外部类
val numOther = 1
inner class InnerClass{ // 嵌套内部类
val name = "InnerClass"
fun init(){
println("我是内部类")
}
}
}
fun main(args: Array<String>) {
Other().InnerClass().init() // 调用格式为:外部类().内部类().内部类方法/属性
}
注意:
- 调用内部类的属性或方法的格式为:
外部类().内部类().内部类方法/属性。在调用的时候嵌套类是需要实例化的
。- 内部类不能使用外部类的属性和成员
2.2、匿名内部类
作为一名
Android
开发者,对匿名内部类都不陌生,因为在开发中,匿名内部类随处可见。比如说Button
的OnClickListener
,ListView
的单击、长按事件等都用到了匿名内部类。
一般的使用方式为定义一个接口,在接口中定义一个方法。
例:
class Other{
lateinit private var listener : OnClickListener
fun setOnClickListener(listener: OnClickListener){
this.listener = listener
}
fun testListener(){
listener.onItemClick("我是匿名内部类的测试方法")
}
}
interface OnClickListener{
fun onItemClick(str : String)
}
fun main(args: Array<String>){
// 测试匿名内部类
val other = Other()
other.setOnClickListener(object : OnClickListener{
override fun onItemClick(str: String) {
// todo
println(str)
}
})
other.testListener()
}
输出结果为:
我是匿名内部类的测试方法
3、局部类
所谓局部类,这一点和
Java
是一致的。即定义在方法(函数)中的类。
例:
class Other{ // 外部类
val numOther = 1
fun partMethod(){
var name : String = "partMethod"
class Part{
var numPart : Int = 2
fun test(){
name = "test"
numPart = 5
println("我是局部类中的方法")
}
}
val part = Part()
println("name = $name \t numPart = " + part.numPart + "\t numOther = numOther")
part.test()
println("name = $name \t numPart = " + part.numPart + "\t numOther = numOther")
}
}
fun main(args: Array<String>) {
// 测试局部类
Other().partMethod()
}
输出结果为:
name = partMethod numPart = 2 numOther = 1
我是局部类中的方法
name = test numPart = 5 numOther = 1
通过上面的实例:我们可以看出:
- 局部类只能在定义该局部类的方法中使用。
- 定义在实例方法中的局部类可以访问外部类的所有变量和方法。但不能修改
- 局部类中的可以定义属性、方法。并且可以修改局部方法中的变量。
转载 https://www.cnblogs.com/Jetictors/p/8183254.html