一、继承、类型转换、Any超类
继承
Kotlin中类默认都是封闭的,要让某个类开放继承,必须使用open关键字修饰它。
open class Product(val name: String) { fun description() = "Product: $name" open fun load() = "Nothing..." } /** * 继承 * 类默认都是封闭的,要让某个类开放继承,必须使用open关键字修饰它。 */ class LuxuryProduct : Product("Luxury") { override fun load() = "LuxuryProduct loading..." fun special() = "LuxuryProduct special function" } fun main() { val p: Product = LuxuryProduct() println(p.load()) /** * 类型监测 等同于java中的instanceof * Kotlin的is运算符是个不错的工具,可以用来检查某个对象的类型 * * 解释:这里检查p变量的运行时类型,是否是Product类型,或者Product类型的子类型。 * 这里的p对象的运行时类为LuxuryProduct类 */ println(p is Product) println(p is LuxuryProduct) println(p is File) /** * 类型转换 * as操作符声明,这是一个类型转换 */ println((p as LuxuryProduct).special()) if (p is LuxuryProduct) { println((p as LuxuryProduct).special()) } /** * 智能类型转换 * Kotlin编译器很聪明,只要能确定any is 父类条件检查属实,它就会将 * any当做子类类型对待,因此,编译器允许你不经类型转换直接使用。 */ println(p.special()) /** * Kotlin层次 * 无须在代码里显示指定,每一个类都会继承一个共同的叫做Any的超类 */ println(p is Any) /** * Any类提供的这几个方法,在Kotlin编译器内部已经实现 * 因为Kotlin的跨平台性,在不同平台输出的格式也不一样,所以在编译器内部进行了实现。 */ println(p.toString()) }
输出结果如下
LuxuryProduct loading... true true false LuxuryProduct special function LuxuryProduct special function LuxuryProduct special function true com.king.kotlin.kotlin04.LuxuryProduct@135fbaa4 Process finished with exit code 0
二、object关键字详解
使用object关键字有三种方式
- 对象声明
- 对象表达式
- 伴生对象
1、对象声明
/** * object关键字,你可以定义一个只能产生一个实例的类-单例 * 使用object关键字有三种方式 * 1.对象声明:对象声明有利于组织代码和管理状态,尤其是管理整个应用 * 运行生命周期内的某些一致性状态。 * 2.对象表达式 * 3.伴生对象 */ object ApplicationConfig { init { println("ApplicationConfig loading...") } fun doSomething() { println("doSomething") } } fun main() { //这里ApplicationConfig既是类名,又是对象名 ApplicationConfig.doSomething() println(ApplicationConfig) println(ApplicationConfig) }
输出结果如下
ApplicationConfig loading... doSomething com.king.kotlin.kotlin04.ApplicationConfig@28d93b30 com.king.kotlin.kotlin04.ApplicationConfig@28d93b30
2、对象表达式
open class Player { open fun load() = "loading nothing" } fun main() { /** * 对象表达式 * 有时候你不一定非要定义一个新的命名类不可,也许你需要某个现有类的一种变体实例, * 但只需要用一次就行了,事实上,对于这种用完就丢的类实例,连命名就可以省了。 * 这个对象表达式是XX的子类,这个匿名类依然遵循object关键字的一个规则,即一旦实例化 * 该匿名类只能有唯一一个实例存在。 */ val p = object : Player() { override fun load() = "anonymous nothing..." } println(p.load()) }
输出结果如下
anonymous nothing...
3、伴生对象
open class ConfigMap { /** * 伴生对象 * 如果你想将某个对象的初始化和一个类实例捆绑在一起,可以考虑使用伴生对象, * 使用companion修饰符,你可以在一个类定义里声明一个伴生对象,一个类里只能有一个 * 伴生对象。 */ companion object { private const val PATH = "D:\\android.txt" fun load() = File(PATH).readText() } } fun main() { println(ConfigMap.load()) }
输出结果如下
great ssss