本小節主要介紹kotlin接口類、抽象類、伴生對象的相關知識。
1、kotlin的接口
在Java中,從jdk8開始,Java的接口中可以有預設方法的實作。kotlin的接口與Java相似。
1.1、kotlin定義接口,關鍵字Interface
interface A {
fun method()
}
kotlin 接口類中的方法可以實作,也可以不實作。
interface A {
// 加上 花括号就可以實作,不加就不實作
fun method() {
println("A")
}
}
1.2、kotlin接口類的實作
interface A {
// 加上 花括号就可以實作,不加就不實作
fun method() {
println("A")
}
}
下面是對接口的實作。
class C : A {
// 方法重寫
override fun method() {
println("C")
}
}
1.3、kotlin接口的實作和繼承相同名稱的方法
在kotlin中,當接口的名字和要繼承類中有相同方法名時,kotlin使用 super<Class>.method() 來區分兩個不同類中的方法。
// 接口類
interface A {
// 加上 花括号就可以實作,不加就不實作
fun method() {
println("A")
}
}
// 普通類
open class B {
open fun method() {
println("B")
}
}
以上類中竄在相同的方法名,此時:
/**
* C 繼承了B,并實作了 A,裡面都有method方法,比較混亂,是以必須要明确使用的那個方法
*
* 擁有簽名的相同的方法,必須明确,使用 super<Class>.method()
*/
class C: A,B() {
override fun method() {
println("C")
super<A>.method()
super<B>.method()
}
}
2、kotlin中的抽象類
kotlin中的抽象類和Java中的抽象類基本上類似。 使用 abstract 關鍵字進行修飾
/**
* 抽象類
*/
open class BaseClass {
open fun baseMethod() {
}
}
abstract class ChildCLass: BaseClass() {
}
3、kotlin的伴生對象
3.1、對象聲明
在Java送使用 new 關鍵字,将對象建立出來并且放在記憶體中。但是在kotlin中可以直接聲明一個對象,使用object關鍵字。
// 使用object關鍵字聲明一個對象,叫 MyObject
object MyObject {
fun method() {
println("method")
}
}
上面對象中的方法可以直接被調用。
fun main() {
// 可以直接調用
MyObject.method() // method
}
3.2、伴生對象
補充:
- 在Java中,static關鍵字:一個類被static修飾後,那麼這個類就可以通過類名直接被調用,這也是Java鼓勵的一種調用方式。
- 我們可以吧Java中的static的方法當做一種全局方法,但是在kotlin中 沒有static的方法。
- 在大多數情況下,kotlin推薦的做法是使用 包級别 的函數作為靜态方法。
- 是以,kotlin會将包級别的函數當做靜态方法來看。
companion object : 伴生對象
伴生對象: 随着類的存在而存在,相當于實作了Java中的 static 方法,在kotlin中使用 companion關鍵字來修飾。
class MyTest() {
/**
* 定義類(伴生對象)
* MyObject伴随 MyTest 類而存在
*
* @MyObject :類似于重命名,作用不大,可以省略
* kotlin中提供了預設的名字 Companion
*/
companion object MyObject {
val A: Int = 100;
@JvmStatic
fun method() {
println("this is companion object")
}
}
}
伴生對象和 static對象的關系:
- kotlin中将 MyObject類以MyTest的内部類的方式而存在。
- 注意: 雖然伴生對象的成員看似是Java中的靜态成員,但是在運作期,他們依舊是真實對象的執行個體對象
- 在Java上,kotlin可以使用讓伴生對象成為真正的靜态方法與屬性,使用 @JvmStatic 注解來實作
- 伴生對象在編譯後會生成一個靜态内部類 (可以通過反編譯實作)
3.3、反編譯伴生對象類
下面通過反編譯的方式展示kotlin的伴生對象與Javastatic修飾類的關系。
使用javap指令反編譯上面的kotlin編譯後生成的位元組碼:
Compiled from "ObjectDeclaration.kt"
public final class com.liang.kotlin.classAndObject.MyTest {
public static final com.liang.kotlin.classAndObject.MyTest$MyObject MyObject;
public com.liang.kotlin.classAndObject.MyTest();
static {};
public static final int access$getA$cp();
public static final void method();
}
關于kotlin反編譯的知識,可以看我之前的教程,點這裡。
通過上面反彙編出來的内容我們看到了類的結構,就是Java中的 static 修飾的類,進一步看該類的詳細内容:
Compiled from "ObjectDeclaration.kt"
public final class com.liang.kotlin.classAndObject.MyTest {
public static final com.liang.kotlin.classAndObject.MyTest$MyObject MyObject;
public com.liang.kotlin.classAndObject.MyTest();
Code:
0: aload_0
1: invokespecial #8 // Method java/lang/Object."<init>":()V
4: return
static {};
Code:
0: new #39 // class com/liang/kotlin/classAndObject/MyTest$MyObject
3: dup
4: aconst_null
5: invokespecial #44 // Method com/liang/kotlin/classAndObject/MyTest$MyObject."<init>":(Lkotlin/jvm/internal/DefaultConstructorMarker;)V
8: putstatic #37 // Field MyObject:Lcom/liang/kotlin/classAndObject/MyTest$MyObject;
11: bipush 100
13: putstatic #20 // Field A:I
16: return
public static final int access$getA$cp();
Code:
0: getstatic #20 // Field A:I
3: ireturn
public static final void method();
Code:
0: getstatic #37 // Field MyObject:Lcom/liang/kotlin/classAndObject/MyTest$MyObject;
3: invokevirtual #41 // Method com/liang/kotlin/classAndObject/MyTest$MyObject.method:()V
6: return
}