您当前的位置: 首页 >  kotlin

Kevin-Dev

暂无认证

  • 0浏览

    0关注

    544博文

    0收益

  • 0浏览

    0点赞

    0打赏

    0留言

私信
关注
热门博文

【Kotlin -- 知识点】枚举类、接口类

Kevin-Dev 发布时间:2022-02-16 08:58:46 ,浏览量:0

在这里插入图片描述

文章目录
    • 一、接口
      • 1. 简单使用
      • 2. 接口中的函数使用
      • 3. 接口中的属性使用
      • 4. 接口的冲突问题解决
    • 二、枚举类
      • 1. 声明方式及枚举常量
      • 2. 枚举常量的初始化
      • 3. 枚举常量的匿名类
      • 4. 枚举类的使用
      • 5. 源码分析

Kotlin 也是面向对象编程。面向对象的语言是可以创建类的。类就是对事物的一种封装,比如人、汽车、房子等任何事物,我们都可以将它们封装成一个类,而类中又可以拥有自己的字段和函数。

一、接口 1. 简单使用
  • 声明

关键字:interface 定义格式: interface 接口名 { … }

  • 用法
  • 使用冒号( : ),这一点是和Java不同的。Java中使用接口使用的是implements关键字
  • 在Kotlin中冒号( : ) 使用的地方很多:用于变量的定义、用于继承、用于接口、方法的返回类型声明 使用格式: class 类名 : 接口名 { // 重写的接口函数、属性等 … }
  • 实例
/**
 * 我定义的接口
 */
interface Demo1Interface{

    // 定义的方法
    fun fun1()
}

/**
 * 接口的实现类
 */
class Demo1 : Demo1Interface{
    override fun fun1() {
        println("我是接口中的fun1方法")
    }
}

fun main(args: Array) {

   // 类的初始化
   var demo = Demo1()

   demo.fun1()
}

输出结果:

我是接口中的fun1方法

2. 接口中的函数使用

不带结构体的函数可以省略大括号,且不用强制重写带结构体的函数就可以直接调用。不太明白也没关系,下面的代码中都有注释。

interface Demo2Interface{

    /**
     * 定义一个无参数无返回值的方法
     */
    fun fun1()

    /**
     * 定义一个有参数的方法
     */
    fun fun2(num: Int)

	 /**
     * 定义一个有参数有返回值的方法
     */
    fun fun3(num: Int) : Int
	
	 // 下面的两个方法是有结构体, 故可以不重写
	 
	 /**
     * 定义一个无参数有返回值的方法
     */
    fun fun4() : String{
        return "fun4"
    }

	/**
     * 定义一个无结构体函数,大括号是可以省略的
     */
    fun fun5(){
        // 如果函数中不存在表达式,大括号可以省略。
        // 如fun1一样
    }
}
class Demo2 : Demo2Interface{

    override fun fun1() {
        println("我是fun1()方法")
    }

	override fun fun2(num: Int) {
        println("我是fun2()方法,我的参数是$num")
    }

	override fun fun3(num: Int): Int {
        println("我是fun3()方法,我的参数是$num,并且返回一个Int类型的值")
        return num + 3
    }

	override fun fun4(): String {        
		println("我是fun4()方法,并且返回一个String类型的值")        
		/*            
	 	接口中的fun4()方法默认返回”fun4“字符串.            
	 	可以用super.fun4()返回默认值            
	 	也可以不用super关键字,自己返回一个字符串        
	 	*/        
	 	return super.fun4()    
	}
}

fun main(args: Array) {    
	var demo = Demo2()    
	demo.fun1()    
	demo.fun2(5)    
	println(demo.fun3(10))    
	println(demo.fun4())    
	
	//可以不重写该方法直接调用    
	demo.fun5()
}

输出结果:

我是fun1()方法 我是fun2()方法,我的参数是5 我是fun3()方法,我的参数是10,并且返回一个Int类型的值 13 我是fun4()方法,并且返回一个String类型的值 fun4

3. 接口中的属性使用

在接口中申明属性。接口中的属性要么是抽象的,要么提供访问器的实现。接口属性不可以有后备字段。而且访问器不可以引用它们。

3.1 作为抽象 即重写属性的时候是在实现类的类参数中。这也是用代码提示去重写的实现方法

interface Demo3Interface{

    val num1: Int

    val num2 : Int  
}

class Demo3(override val num1: Int, override val num2: Int) : Demo3Interface{    
	fun sum() : Int{        
		return num1 + num2    
	}
}

fun main(args: Array) {
    var demo = Demo3(1,2)
    println(demo.sum())
}

输出结果:

3

3.2 作为访问器 即手动方式去实现重写,并提供 get() 方法

interface Demo3Interface{     
	// 声明变量并提供默认值     
	// 注意: val num3: Int = 3  这种方式不提供,直接报错    
	val num3: Int    
	get() = 3    

	val num4: Int
}

class Demo3(override val num1: Int, override val num2: Int) : Demo3Interface {    
	// 提供访问器实现    
	override val num3: Int        
	get() = super.num3    

	// 手动赋值    
	override var num4: Int = 4    
	fun result() : Int{        
		return num3 + num4    
	}
}

fun main(args: Array) {    
	println(demo.result())    

	// 在这里也可以改变接口属性的值    
	demo.num4 = 10    
	println(demo.result())
}

输出结果:

7 13

4. 接口的冲突问题解决

该问题是指当我们在父类中声明了许多类型,有可能出现一个方法的多种实现。

interface Demo4InterfaceOne{    
	fun fun1(){        
		println("我是Demo4InterfaceOne中的fun1()")    
	}    

	fun fun2(){        
		println("我是Demo4InterfaceOne中的fun2()")    
	}
}

interface Demo4InterfaceTwo{    
	fun fun1(){        
		println("我是Demo4InterfaceTwo中的fun1()")    
	}    

	fun fun2(){        
		println("我是Demo4InterfaceTwo中的fun2()")    
	}
}

class Demo4 : Demo4InterfaceOne,Demo4InterfaceTwo{    
	override fun fun1() {        
		super.fun1()        
		super.fun1()    
	}    
	
	override fun fun2() {        
		super.fun2()        
		super.fun2()    
	}
}

fun main(args: Array) {    
	// 类的初始化    
	val demo = Demo4()    
	demo.fun1()    
	demo.fun2()}

输出结果:

我是Demo4InterfaceOne中的fun1() 我是Demo4InterfaceTwo中的fun1() 我是Demo4InterfaceOne中的fun2() 我是Demo4InterfaceTwo中的fun2()

说明:Demo4 实现了 Demo4InterfaceOneDemo4InterfaceTwo 两个接口,而两个接口中都存在两个相同方法名的方法。因此编译器不知道应该选哪个,故而我们用super.方法名来区分。

二、枚举类 1. 声明方式及枚举常量
  • 关键字:enum
  • 枚举常量:即枚举类下的对象,每个枚举类包含0个到多个枚举常量。
  • 声明 enum 关键字在类头中的 class 关键字前面 声明格式:
enum class 类名{
    ...
}
  • 枚举常量

枚举类中的每一个枚举常量都是一个对象,并且他们之间用逗号分隔。

栗子:关于一个网络请求结果的枚举类

enum class State {    
	/*       
	   NORMAL : 正常       
	   NO_DATA : 数据为空       
	   NO_INTERNET : 网络未连接       
	   ERROR : 错误       
	   OTHER : 其他    
	*/    
	NORMAL,NO_DATA,NO_INTERNET,ERROR,OTHER
}
  • 访问枚举常量

不需要实例化枚举类就可以访问枚举常量

使用方式为:

枚举类名.枚举常量.属性

// 使用中缀符号访问枚举常量
State.NORMAL.name
State.NO_DATA.name
State.NO_INTERNET.name
State.ERROR.name
State.OTHER.name
2. 枚举常量的初始化

因为每一个枚举都是枚举类的实例,所以他们可以是初始化过的。

enum class Color(var argb : Int){
    RED(0xFF0000),
    WHITE(0xFFFFFF),
    BLACK(0x000000),
    GREEN(0x00FF00)
}
3. 枚举常量的匿名类
  • 要实现枚举常量的匿名类,则必须提供一个抽象方法(必须重写的方法)。且该方法定义在枚举类内部。而且必须在枚举变量的后面。
  • 枚举变量之间使用逗号(,)分割开。但是最后一个枚举变量必须使用分号结束。不然定义不了抽象方法。
  • 在上面已经说过,每一个枚举常量就是一个对象。
enum class ConsoleColor(var argb : Int){
	RED(0xFF0000){
        override fun print() {
            println("我是枚举常量 RED ")
        }
    },
    WHITE(0xFFFFFF){
        override fun print() {
            println("我是枚举常量 WHITE ")
        }
    },
    BLACK(0x000000){
        override fun print() {
            println("我是枚举常量 BLACK ")
        }
   },
   GREEN(0x00FF00){
        override fun print() {
            println("我是枚举常量 GREEN ")
        }
    };
    abstract fun print()
}

fun main(args: Array) {
    ConsoleColor.BLACK.print()
}

输出结果:

我是枚举常量 BLACK

4. 枚举类的使用
  • 每个枚举常量都包含两个属性:name(枚举常量名)和ordinal(枚举常量位置)
  • 提供了values()和valueOf()方法来检测指定的名称与枚举类中定义的任何枚举常量是否匹配。
  • 自 Kotlin 1.1起,可以使用 enumValues()和 enumValueOf()函数以泛型的方式访问枚举类中的常量。
  • 访问枚举变量属性
fun main(args: Array) {    
	println("name = " + Color.RED.name + "\tordinal = " + Color.RED.ordinal)    
	println("name = " + Color.WHITE.name + "\tordinal = " + Color.WHITE.ordinal)    
	println("name = " + Color.BLACK.name + "\tordinal = " + Color.BLACK.ordinal)    
	println("name = " + Color.GREEN.name + "\tordinal = " + Color.GREEN.ordinal)
}

enum class Color(var argb : Int){
     RED(0xFF0000),
     WHITE(0xFFFFFF),
     BLACK(0x000000),
     GREEN(0x00FF00)
}   

输出结果:

name = RED ordinal = 0 name = WHITE ordinal = 1 name = BLACK ordinal = 2 name = GREEN ordinal = 3

  • 使用 enumValues()enumValueOf() 访问
println(enumValues().joinToString { it.name })
println(enumValueOf("RED"))

输出结果:

RED, WHITE, BLACK, GREEN RED

  • 使用 valueOf()values() 检测
	println(Color.valueOf("RED"))
    println(Color.values()[1])
    println(Color.values()[2])

输出结果:

RED WHITE BLACK

5. 源码分析

Enum.kt这个源文件。在这里我大致的说明一下这个源文件的方法、属性等。有兴趣的可以去看看这个源文件。其实里面也没几个方法。

public abstract class Enum(name: String, ordinal: Int): Comparable{    
	companion object {}    

	public final val name: String    

	public final val ordinal: Int    

	public override final fun compareTo(other: E): Int    

	protected final fun clone(): Any    

	public override final fun equals(other: Any?): Boolean    

	public override final fun hashCode(): Int    

	public override fun toString(): String}

默认实现了companion object {}, 这也是我们访问枚举常量无需实例化枚举类的原因

仅提供了两个属性,即我们上面用到的枚举常量名称(name)和枚举常量位置(ordinal)

实现了Comparable接口,这也是我们能获取枚举常量位置的原因

关注
打赏
1658837700
查看更多评论
立即登录/注册

微信扫码登录

0.1666s