阅读 214

Kotlin——中级篇(八): 类型别名与属性名冲突解决

严格来说,这个系列教程应该是去年就写完了,但是由于自身的懒惰等原因致使其从去年7月份(2018)停更到现在。至此把这个系列教程捡起来写完它,希望能得到各位看客的原谅与支持。

今天这篇文章详细的讲解kotlin中的类型别名,以及实体类中属性名和关键字冲突的解决方法。

目录

一、类型别名

  • 关键字 : typealias
  • 作用 :为现有类型提供替代名称。 解决代码过于冗余与臃肿的问题

在开发中,命名过长、或者泛型等使代码过于冗余与臃肿,我们可以使用类型别名引入较短的名称,并使用新的名称替代原类型。这里从类名、函数参数、泛型三个方便讲解。

1.1、类名

例1 :普通类

// 类型别名,切记声明在顶部
typealias First = TypeAliasDemoTestFirst
typealias Second = TypeAliasDemoTestSecond

// 测试类
class TypeAliasDemoTestFirst{
    fun show(){
        println("name : ${this.javaClass.simpleName}")
    }
}
class TypeAliasDemoTestSecond{
    fun show(){
        println("name : ${this.javaClass.simpleName}")
    }
}

fun main(){
    val first = First()
    first.show()

    val second = Second()
    second.show()
}
复制代码

例2 :嵌套类与内部类

typealias NestA = DemoClassTestNest.A
typealias NestB = DemoClassTestNest.B

typealias InnerA = DemoClassTestInner.A
typealias InnerB = DemoClassTestInner.B

class DemoClassTestNest{
    class A{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
    class B{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
}

class DemoClassTestInner{
    class A{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
    class B{
        fun show(){
            println("name : ${this.javaClass.simpleName}")
        }
    }
}

fun main(){
     val nestA = NestA()
    nestA.show()

    val nestB = NestB()
    nestB.show()

    val innerA = InnerA()
    innerA.show()

    val innerB = InnerB()
    innerB.show()
}
复制代码

1.2、函数参数

当我们定义一个高阶函数,其参数过长的时候,也可以使用类型别名去美化代码。下面列举两个例子大家就明白了。当然,若您还不了解高阶函数。请参见我的另一篇文章。Kotlin——高级篇(二):高阶函数详解与标准的高阶函数使用

例1、:官网上的例子

// 定义一个返回值为Boolean类型的函数为另一个函数的参数,把这个函数参数定义为`Predicate<T>`的别名
typealias Predicate<T> = (T) -> Boolean    

// 定义的高阶函数
fun foo1(p : Predicate<Int>) = p(2)
fun foo2(p : Predicate<String>) = p("test")

fun main(){
    // 条件,即函数参数为{it > 0},返回值时Boolean类型,其这里的it指的就是泛型T,确定为了Int型 
    val f1: (Int) -> Boolean = { it > 0 }
    // 即把2带入foo1函数中,经过上面的条件,判断出 2 > 0 故而应该输出为true
    println(foo1(f1))

    val f2 : (String) -> Boolean = {it == "xxx"}
    println(foo2(f2)) //这里输出为false, 很显然,"test" != "xxx"
}
复制代码

输出结果:

true
false
复制代码

例2: 自定义一个难一点儿,安卓adapter中的item事件编写

// 这里可以注释,标明参数的含义
// typealias ItemListener = (Int, String)? -> Unit   

或者像这样定义:
typealias ItemListener = (pos : Int, item : String)? -> Unit   

class TestAdapter(val context : Context , val data: MutableList<String>)
: RecyclerView.Adapter<TestAdapter.TestViewHolder>(){

    private var mListener : ItemListener = null

    override fun onBindViewHolder(holder: TestViewHolder?, position: Int) {
        ...
        holder?.itemView?.setOnClickListener {
            mListener?.invoke(position, data[position])
        }
    }

    override fun onCreateViewHolder(parent: ViewGroup?, viewType: Int): TestViewHolder {
        return TestViewHolder(View.inflate(context,layoutId,parent))
    }

    override fun getItemCount(): Int {
        return data.size
    }

    fun setOnItemClickListener(mListener : ItemListener){
        this.mListener = mListener
    }

    inner class TestViewHolder(itemView : View) : RecyclerView.ViewHolder(itemView)
}

// 调用
TestAdapter(this,dataList).setOnItemClickListener { position, item ->
    Toast.makeText(this,"$position \t $item",Toast.LENGTH_SHORT).show()
}
复制代码

1.3、泛型

例1、:列表嵌套列表的情况

typealias MutListData = MutableList<MutableList<Int>>

fun main(){
    val data : MutListData = mutableListOf()
    val item1 = mutableListOf(1,3,5,7)
    val item2 = mutableListOf(2,4,6,8)
    data.add(item1)
    data.add(item2)

    data.asSequence().flatMap { it.asSequence() }.forEach { println("value : $it") }
}
复制代码

输出结果 :

value : 1 	value : 3 	value : 5 	value : 7 	value : 2 	value : 4 	value : 6 	value : 8 	
复制代码

例2、自定义泛型类,项目中常见的例子

typealias MapModelData<T> = Map<String, BaseModel<T>>

data class BaseModel<T>(val code : Int,
                    val msg : String,
                    val data : T){
                        
     override fun toString(): String {
        return "BaseModel(code=$code, msg='$msg', data=$data)"
    }                    
}
                    
fun main(){
    val dataModel : MapModelData<Int> = mutableMapOf()
    val model1 = BaseModel<Int>(1,"test 1", 1)
    val model2 = BaseModel<Int>(2,"test2", 2)
    dataModel.put("1" , model1)
    dataModel.put("2" , model2)

    dataModel.forEach { key, value ->
        println("key : $key value : ${value.toString()}")
    }
}
复制代码

输出结果:

key : 1 value : BaseModel(code=1, msg='test 1', data=1)
key : 2 value : BaseModel(code=2, msg='test2', data=2)
复制代码

二、属性名冲突解决

在开发中,处理json字符串转换成实体类的时候,会出现属性名和关键字冲突的问题。下面实现Javakotlin的解决方案。

2.1、Java的解决方案

Java使用@SerializedName注解

Java例子:

public class Test{
    private int id;
    private String name;
    @SerializedName("swicth")
    private int s;
}
复制代码

2.2、Kotlin的解决方案

Kotlin中,无需像Java一样引注解,只需要把属性名包括在符号( `` )中即可。这个符号是英文输入法下的Tab键上面的一个键。

Koltin例子

data class TestBean(val id : Int,
                val name : String,
                val `package` : String)
复制代码

PS : 这种情况在开发中一般不会出现。因为开发人员都会注重命名规范。但是偶尔出现的时候我们可以使用上面的知识去解决。

三、总结

上面的知识点虽然很简单,在开发中也不是很常用,但是对于项目开发而言,类型别名还是请大家掌握,在代码美观、简洁上是很有作用的

源代码

如果各位大佬看了之后感觉还阔以,就请各位大佬随便star一下,您的关注是我最大的动力。
我的个人博客Jetictors
我的githubJetictors

欢迎各位大佬进群共同研究、探索

QQ群号:497071402

关注下面的标签,发现更多相似文章
评论