【Kotlin -- 知识点】抽象类、内部类

一、抽象类

在实际的开发程序的时候,一般都会写一个基类,封装常用方法、以及处理一些共有的逻辑,但是程序逻辑是根据每个类不同的功能实现不同的代码。而这个所谓的基类,一般都是一个抽象类。

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

小结:

  • 抽象类本身具有普通类特性,以及组成部分。不过值得注意的是,抽象类不能直接被实例化
  • 其抽象了类的子类必须全部重写带 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的设计模式中,有一种设计模式叫模板设计模式,其定义为:
  • 定义一个操作中算法的骨架,而将一些步骤延迟到子类中,模板方法使得子类可以不改变算法的结构即可重定义该算法的某些特定步骤。
  • 通俗点的理解就是:完成一件事情,有固定的数个步骤,但是每个步骤根据对象的不同,而实现细节不同;就可以在父类中定义一个完成该事情的总方法,按照完成事件需要的步骤去调用其每个步骤的实现方法。每个步骤的具体实现,由子类完成。

二、内部类(嵌套类)

在实际开发中,用到内部类的地方是很多的。比如说:

  • 对于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. 内部类

在上面的例子中讲解了嵌套类的使用,而内部类和嵌套类还是有一定的区别的,而且内部类是有特定的关键字去声明的。

  • 关键字
    声明一个内部类使用 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()  // 调用格式为:外部类().内部类().内部类方法/属性
}

说明:

  • 调用内部类的属性或方法的格式为:外部类().内部类().内部类方法/属性。在调用的时候外部类、内部类都是需要实例化的
  • 内部类可以访问外部类的属性和成员
  • 匿名内部类
    作为一名 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. 局部类

所谓局部类,即定义在方法(函数)中的类。
例子:

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

小结:

  • 局部类只能在定义该局部类的方法中使用。
  • 定义在实例方法中的局部类可以访问外部类的所有变量和方法。但不能修改
  • 局部类中的可以定义属性、方法。并且可以修改局部方法中的变量。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Kevin-Dev

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值