大风起兮云飞扬,
威加海内兮归故乡,
安得猛士兮守四方
——刘邦 ·《卜算子》
你是否为一个变量类型过长而纠结过、吐槽过?那么这篇文章详细的讲解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、函数参数
当我们定义一个高阶函数,其参数过长的时候,也可以使用类型别名去美化代码。下面列举两个例子大家就明白了
例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字符串转换成实体类的时候,会出现属性名和关键字冲突的问题。下面实现Java与kotlin的解决方案。
2.1、Java的解决方案
在
Java使用@SerializedName注解
public class Test{
private int id;
private String name;
@SerializedName("swicth")
private int s;
}
2.2、Kotlin的解决方案
在
Kotlin中,无需像Java一样引注解,只需要把属性名包括在符号( `` )中即可。这个符号是英文输入法下的Tab键上面的一个键。
data class TestBean(val id : Int,
val name : String,
val `package` : String)
这种情况在开发中一般不会出现。因为开发人员都会注重命名规范。但是偶尔出现的时候我们可以使用上面的知识去解决。
三、总结
上面的知识点虽然很简单,在开发中也不是很常用,但是对于项目开发而言,类型别名还是请大家尽量掌握,因为其在代码美观、简洁上是很有作用的,不过如果滥用的话,会对代码维护提升不小的难度
本文已收录至GitHub: Jetictors/KotlinLearn,欢迎star
文章持续更新中,可以微信搜索「J佬杂谈 」第一时间阅读, 大家的三连击是对老J最好的动力了,你确定不来一波吗?
如果本篇博客有任何错误和建议,欢迎人才们留言