Kotlin学习笔记三2.0:联系人列表(面向对象版本)

 系列文章目录

 Kotlin学习笔记三:联系人列表

前言

上期主要讲了联系人列表这一个demo,接下来咱们在用面向对象的方法来完善我们的项目。主要涉及到的知识点有jar包的引用,单例对象,伴生对象,以及使用的各种函数。

一、前期准备

项目UML类图如下(会与项目有所不同):

二、主要代码

1.操作见面(OperationInterface类)

代码如下(示例):

import InputOperation.inputInt
import InputOperation.inputPersonName
import java.util.*

/**
 * 第1步.显示操作界面
 * 创建一个单例
 * 这种设计使得操作界面的逻辑和显示分离,使得代码更清晰、可维护性更强。
 */

//这里 OperationInterface 类的构造函数是私有的
// (private constructor())这意味着这个类不能在类的外部被直接实例化。
// 只能在类的内部创建实例。
class OperationInterface private constructor(){
    //伴生对象 (companion object) 是 Kotlin 的一种特性,它允许在类内部定义一个对象,
    // 这个对象与类相关联,并且可以像静态成员一样被访问。
    // 在 companion object 内部定义的成员可以直接通过类名访问。
    companion object{
        //在伴生对象中,定义了一个名为 instance 的 val,其类型是 OperationInterface。
        // instance 使用 by lazy 进行初始化,这意味着 OperationInterface 实例的创建是延迟的
        // 只有在第一次访问 instance 时才会创建实例。
        // 这种方式确保了线程安全,并且在多线程环境下也只会创建一个实例。
        val instance:OperationInterface by lazy {
            OperationInterface()
        }
    }
    //显示菜单
    fun showMenu(){
        println("----------------------")
        println("1. 添加好友")
        println("2. 删除好友")
        println("3. 显示列表")
        println("4. 退出")
        println("----------------------")
    }

    //选择操作
    //创建操作的类型
    fun choose() {
        //因为选择的方法不同,每个对应相应的函数
        when (val interfaceInput = inputInt()) {
            3 -> ContactExt.instance.show()
            4 -> ContactExt.instance.exit()
            else -> {
                val name = inputPersonName()
                when (interfaceInput) {
                    1 -> ContactExt.instance.add(name)
                    2 -> ContactExt.instance.delete(name)
                }
            }
        }
    }
}

2.联系人管理类(ContactExt类)

代码如下(示例):

import kotlin.system.exitProcess

/**
 * 第二步.联系人管理类
 * 存储联系人
 * 与外界交互
 */
class ContactExt private constructor(){
    //创建单例,只有一个
    companion object {
        /**
         * 三种方法。。。。。。6:05
         * by lazy 懒加载
         * 定义时不加载,使用时才加载
         * 只会被加载一次
         */
        val instance: ContactExt by lazy {
            ContactExt()
        }
    }


    //容器保存所有联系人
    private val sectionList:ArrayList<Section> = ArrayList()
    //保存每个小组的组名
    private val titles: ArrayList<Char> = arrayListOf()
    //两种创建 ArrayList 实例的方式稍有不同,但在功能上是等效的

    //添加好友
    fun add(name:String){
        addFriend(Person().apply { this.name = name })
    }

    private fun addFriend(person: Person) {
        //判断有没有自己的小组
        if (titles.contains(person.title)){
            //找到section
            for (section in sectionList){
                if (section.title == person.title){
                    section.add(person)
                    break
                }
            }
        }else{
            val section = Section(person.title, arrayListOf(person))
            sectionList.add(section)
            titles.add(person.title)
        }
        //对section排序
        sectionList.sortBy {
            it.title
        }
    }

    fun delete(name:String) {
        val person = Person().apply { this.name = name }
        //判断组名有没有
        if (titles.contains(person.title)) {
            for (section in sectionList) {
                //找到要删除的人
                if (section.title == person.title) {
                    section.delete(person.name)
                    //若该小组没人,则删除标题
                    if (section.friendList.isEmpty()) {
                        sectionList.remove(section)
                        titles.remove(person.title)
                    }
                    break
                }
            }
        }
    }

    fun show(){
        sectionList.forEach { it.show() }
    }

    fun exit(){
        exitProcess(1)
    }
}

3.创建小组列表(Section)

/**
 * 第3步.创建小组列表
 */

class Section(val title:Char,val friendList:ArrayList<Person>) {
    fun add(person:Person){
        friendList.add(person)
        //下一步对person排序
        friendList.sortWith(person)
    }

    fun delete(name:String){
        for (p in friendList){
            if (p.name == name){
                friendList.remove(p)
                break
            }
        }
    }

    fun show(){
        println(title)
        friendList.forEach {
            println(it)
        }
    }
}

 4.创建联系人

/**
 * 第四步.创建person类
 * 好友类
 * 基本信息和比较方法
 */
class Person : Comparator<Person> {
    //先初始化
    //在重写方法,存储外部值
    var name:String = ""
        set(value) {
            field = value
            //定义一个object类来
            pinyin = PinyinUtils.toPinyin(value,PinyinType.WORD_FIRST_UPPERCASE)
        }

    var pinyin:String = ""
        set(value) {
            field = value
            title = pinyin.first().uppercaseChar()
            nameAbbr = pinyin.filter { it in 'A'..'Z' }
        }

    var title:Char = '0'

    var nameAbbr:String = "" //名字首字母缩写

    override fun toString(): String {
        return "$name $pinyin"
    }
    //自己制定比较的方式 比较复杂 或者封装
    override fun compare(o1: Person?, o2: Person?): Int {
        if (o1 == null && o2 == null) return 0
        if (o1 != null && o2 == null) return 1
        if (o1 == null && o2 != null) return -1
        //先比较缩略字母
        if (o1!!.nameAbbr != o2!!.nameAbbr)
            return o1.nameAbbr.compareTo(o2.nameAbbr)
        //缩略名相同了 直接比全名
        return o1.pinyin.compareTo(o2.pinyin)
    }
}

 5.创建单例对象(PinyinUtils)

import net.sourceforge.pinyin4j.PinyinHelper
import net.sourceforge.pinyin4j.format.HanyuPinyinCaseType
import net.sourceforge.pinyin4j.format.HanyuPinyinOutputFormat
import net.sourceforge.pinyin4j.format.HanyuPinyinToneType

/**
 * 第五步.
 * 转化大小写
* object 关键字用于创建单例对象
 * 它是一种特殊的类,只能有一个实例存在
* 并且可以直接访问其内部的方法和属性
* 将中文转化为拼音
* 接收中文名
* 返回完整的拼音
 */


object PinyinUtils {
    fun toPinyin(name:String, type: PinyinType):String{
        val format = HanyuPinyinOutputFormat().also {
            it.caseType = if (type == PinyinType.ALL_UPPERCASE)
                HanyuPinyinCaseType.UPPERCASE
            else
                HanyuPinyinCaseType.LOWERCASE
            it.toneType = HanyuPinyinToneType.WITHOUT_TONE
        }
        //遍历name中的每一个中文汉字
        var wholeName: String = ""
        for (word in name) {
            //将这个中文转化为拼音
            val pinyin = PinyinHelper.toHanyuPinyinStringArray(word, format).first()
            if (type == PinyinType.WORD_FIRST_UPPERCASE) {
                val formattedPy = pinyin.replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
                wholeName += formattedPy
            }else wholeName += pinyin
        }
        return wholeName
    }
}

 6.创建枚举类型(PinyinType)

/**
 * 第六步.
 * 创建枚举类型
 * 枚举类型是一种特殊的数据类型,用于定义一组固定的命名常量
 */


enum class PinyinType {
    ALL_LOWERCASE, //全部小写
    ALL_UPPERCASE, //全部大写
    WORD_FIRST_UPPERCASE //首字母大写
}


总结

       通过类与对象的思想,我们可以把事物拆分成多个对象,每块功能各司其职,但又互相关联,并且使我们可以简化程序的复杂度、提高代码的可维护性和可复用性

  • 6
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值