前言
简单介绍一下Kotlin面对对象简介。记录一下,方便自己查阅。
正文
类
类就是具备某些共同特征的实体的集合,它是一种抽象的数据类型,它是对所具有相同特征实体的抽象。
无参数和有参数类
//不带参数[1,2,3等同] //1 class Person1 { } //2 class Person2() { } //3 class Person3 constructor() { } //带参数[1和2等同] //1 class Person1 constructor(name: String, age: Int) { } //2 class Person2(name: String, age: Int) { }
继承
当继承某个类时,需要在这个类的前面加上open关键字。
open class Person1 { } open class Person2(name: String, age: Int) { } //子类继承父类 class Student1:Person1(){ } class Student2(name: String, age: Int):Person2(name, age){ }
一个类只能继承一个父类,不能继承多个父类。
方法重写
被重写的方法,也需要open。
open class Person { open fun askHello(){ } } class Student:Person(){ override fun askHello() { } }
抽象类
抽象方法使用abstract关键字修饰,该方法没有方法体,在使用时需要实现其方法体,当一个类中包含了抽象方法,该类必须使用abstract关键字定义为抽象类。
-
包含抽象方法的类必须声明为抽象类,但抽象类可以不包含任何抽象方法。
-
抽象类是不可以被实例化的,因为抽象方法是没有方法体的,不可以被调用。
abstract class Person { abstract fun askHello() } class Student:Person(){ override fun askHello() { } }
接口
如果一个抽象类中的所有方法都是抽象的,则可以将这个类用另外一种方式来定义,即接口。
接口是一个特殊的抽象类,在定义接口时,需要使用interface关键字来声明。
interface IPlay{ fun onPlay() } class Student:IPlay{ override fun onPlay() { } }
-
接口中的方法都是抽象的,不能实例化对象。
-
当一个类实现接口时,如果这个类是抽象类,则实现接口中的部分方法即可,否则需要实现接口中的所有方法。
-
一个类通过冒号(:)实现接口时,可以实现多个接口,被实现的多个接口之间要用逗号隔开。
-
一个接口可以通过冒号(:)继承多个接口,接口之间用逗号隔开。
常见类
嵌套类
Kotlin中的嵌套类是指可以嵌套在其他类中的类,该类不能访问外部类的成员,内部类指的是可以用inner标记以便能够访问外部类的成员。
class OutClass{ var name:String = "91大神" class InClass{ fun print(){ //error,无法访问name //Log.d(TAG, "print:$name ") } } }
内部类
内部类只需要在嵌套类的基础上添加一个“inner”关键字即可,将其标识为内部类。
class OutClass{ var name:String = "91大神" inner class InClass{ fun print(){ Log.d(TAG, "print:$name ") } } }
-
Kotlin中,将一个类定义在另一个类的内部,不加任何修饰符,则这个类将被默认为是一个嵌套类,如果加上inner修饰,则是一个内部类。
-
Kotlin中的内部类可以访问外部类中的变量,而嵌套类却不可以访问。
枚举类
每个枚举常量都是一个对象,枚举常量用逗号分隔,枚举类的前面用enum关键字来修饰。
enum class Week{ Monday, Tuesday, Wednesday, Thursday, Friday, Saturday, Sunday }
密封类
这个暂时不太理解,略过。
数据类
Kotlin中的数据类型是专门用于存储数据的类 , 一般该类中不定义成员方法。
一般至于在class前添加data即可。
data class Person(val name: String, val age: Int)
Person 是一个数据类,它有两个属性 name 和 age。
比java中定义bean方便多了。
Kotlin 会自动为数据类生成以下方法:
-
equals(other: Any?):用于比较两个对象是否相等。
-
hashCode():用于生成对象的哈希码。
-
toString():用于将对象转换为字符串的表示形式。
-
copy():用于复制对象。
一般情况下 == 比较的是内容(也就是equals方法) , === 比较的是引用。
//true (Person("谷歌", 100) == Person("谷歌",100)) //false (Person("谷歌", 100) === Person("谷歌",100))
-
数据类的主构造函数至少有一个参数,如果需要一个无参的构造函数,可以将构造函数中的参数都设置为默认值。
-
数据类中的主构造函数中传递的参数必须用val或var来修饰。
-
数据类不可以用abstract、open、sealed或inner关键字来修饰。
-
在Kotlin 1.1版本之前数据类只能实现接口,1.1版本之后数据类可以继承其他类。
-
编译器可以自动生成一些常用方法,如equals()、hashCode()、toString()、componentN()、copy()等,这些方法也可以进行自定义。
单例模式
单例模式是通过object关键字来完成的,通过object修饰的类即为单例类,单例类在程序中有且仅有一个实例。
object Singleton { fun doSomething() { println("Doing something.") } } fun main() { Singleton.doSomething() // 确保返回相同的实例 val another = Singleton // 输出: true println(another === Singleton) }
伴生类
由于在Kotlin中没有静态变量,因此它使用了伴生对象来替代Java中的静态变量的作用。伴生对象是在类加载时初始化,生命周期与该类的生命周期一致。
class BiuApp : Application() { companion object { final val TAG = "KApp_"; lateinit var mContext: Context; } override fun onCreate() { super.onCreate() mContext = this; Log.d(TAG, "onCreate: ") } } //类似于static变量 BiuApp.TAG BiuApp.mContext
由于伴生对象可以指定名称,也可以不指定名称,因此在调用伴生对象时分两种情况,具体如下。
(1)有名称:调用方式为“类名.伴生对象名.成员名”或“类名.成员名”。
(2)无名称:调用方式为“类名.Companion.成员名”或“类名.成员名”。
不过,我一般按照上面的,不写伴生类名。
对象
一切皆对象,对象就是一个真实世界中的实体。
对象是类的实例,具有独立的状态和行为。
对象的创建
var student1 = Student1(); var student2 = Student2("百度", 40);
委托
委托模式也叫代理模式,是最常用的一种设计模式。在委托模式中,如果有两个对象参与处理同一个请求,则接受请求的对象将请求委托给另一个对象来处理,简单来说就是A的工作交给B来做。委托模式是实现继承的一个很好的替代方式。在Kotlin中,委托是通过by关键字实现的,并且主要分为两种形式,一种是类委托,一种是属性委托。
委托类
委托是由两个对象完成的,一个是委托类,一个是被委托类。在委托类中并没有真正的功能方法,该类的功能是通过调用被委托类中的方法实现的。
interface IHousework{ fun doHousework(); } class Son:IHousework{ override fun doHousework() { Log.d(TAG, "doHousework by Son: ") } } class Father : IHousework by Son(){ }
上面Father是委托类,没有任何代码,Son是被委托的类。
var father:Father = Father() father.doHousework()
日志打印
doHousework by Son:
另外一种写法。
interface IHousework { fun doHousework(); } class Son : IHousework { override fun doHousework() { Log.d(TAG, "doHousework by Son: ") } } class Father(iHousework: IHousework) : IHousework by iHousework { }
var son = Son(); var father = Father(son) father.doHousework()
打印结果跟上面一样。
延迟加载
在Kotlin中,声明变量或者属性的同时要对其进行初始化,否则就会报异常,尽管我们可以定义可空类型的变量,但有时却不想这样做,能不能在变量使用时再进行初始化呢?为此,Kotlin中提供了延迟加载(又称懒加载)功能,当变量被访问时才会被初始化,这样不仅可以提高程序效率,还可以让程序启动更快。
延迟加载是通过“by lazy”关键字标识的,延迟加载的变量要求声明为val,即不可变变量。
延迟加载也是委托的一种形式。
val lazyTxt: String by lazy { Log.i(TAG,"初始化lazyTxt") "lazy" } Log.d(TAG, " 1 : $lazyTxt") Log.d(TAG, " 2 : $lazyTxt")
日志打印
初始化lazyTxt 1 : lazy 2 : lazy
只初始化了一次。
要求属性声明为val,即不可变变量,在java中相当于被final修饰。
参考文章