几种常用类
抽象类
前面说了 Kotlin 中类的默认修饰是 public final 的,想要被继承就要用 open 声明,而抽象类由于本身不能实例化,因此默认是 open 的。这个和 Java 差别不大。
泛型类
在做泛型抽象时会用的上,一个特定的运用场景就是网络请求时的入参和返回结果的解析。如果要定义一个泛型类,可以像这样,
//在类名后面紧跟泛型声明
class NetResp<T> (var name: String, var data: T){}
数据类
这种类型类似 Java 里面的 Java Bean,但 Java Bean 只是一种规范,这个类在 Kotlin 里有着专门的修饰符 data,声明这样的类好处在于,像一些通用的方法,toString(), equals(), copy() 等都是我们所需要的实现,而不像 Java 里默认的实现,拿 toString() 来说,数据类打印的是 Json 格式的成员变量内容,而 Java 里默认打印的是对象引用地址,不过对于 Kotlin 里的普通类,也是如此,仅仅是数据类特殊。
区分普通类与数据类的好处是,更明显的表明类的用途,并且还很简洁。
by 和 object
类委托
类委托源于 Kotlin 对设计问题的一种解决方案,在设计大型项目时,对继承实现的脆弱型,导致子类的实现已不像最初时设计的那样纯粹,从而导致代码越来越难以维护。简单理解就是随着功能的不断增加,基类的改变就会引起子类的不断变化,原本职责很单一的子类变的不再那么单纯,这也就违背了设计原则。
面对这个问题,Kotlin 是这么解决的,首先让类默认是 final 的,目的是尽量避免继承的滥用吧,其次对于像装饰器模式这样的实现采用了类委托来简化样板代码(装饰器模式也就像类扩展一样,包装类可以实现自己的功能,也可以不做处理转交给真正处理的内部变量,这样的实现例如 Activity 和内部变量 mBase)。
所以用类委托实现,可以避免继承带来的副作用,更加灵活,也可以减少装饰器模式实现带来的样板代码。
class ActivityCopy(val mBase: Context): Context by mBase {}
//这样声明之后,ActivityCopy 就相当于实现了 Context 类里定义的方法,
//并且这些方法内部调用最终由 mBase 的实现类实现
object
核心理念是:用这个关键字声明后就定义了一个类,同时也创建了一个该类的对象实例。
这个关键字非常实用,
- 用在单例模式的实现
- 伴生对象,实现静态方法和静态变量
- 匿名内部类的实现
//像这样定义的类就是单例模式的实现,叫对象声明
object BookManager {
val books = arrayListOf<Book>()
fun findBook(name: String) {
//......
}
}
//引用的时候就可以像这样引用
//BookManager.findBook("朝花夕拾")
在 Java 中我们可以通过 static 来声明静态方法和静态变量,但在 Kotlin 里使用的是伴生对象的概念,当然也有顶层函数可以代替。但与伴生对象的区别是,顶层函数无法访问类的 private 成员。
class TecBook{
//像这样在类的内部,用 companion 关键字修饰 object 就构成了伴生对象
//调用时可以将伴生对象里的方法作为外部类的静态方法来调用
//例如 TecBook.createBook() 这样
companion object {
fun createBook(): TecBook {}
}
}
最后就是匿名内部类的实现了,项目中最常用的就是各种 setListener() 方法的入参实现,在 Kotlin 里用 object 可以这样写,
//例如写一个textview 的点击事件监听
tvRead.setOnClickListener(object: OnClickListener(){
override fun onClick(v: View) {
//其实对照着 Java 的实现来看,无非就是把 new 替换成了 object
//但其实用上 lambda 编程才是 object 作为对象表达式的精髓
//这里暂且先知道怎么用,看得懂就行,实际写的时候,IDE 其实也会给出 lambda 形式的代码,那样更加的简洁。
}
})
网友评论