1. 程式人生 > 程式設計 >Kotlin中的物件表示式和物件宣告的具體使用

Kotlin中的物件表示式和物件宣告的具體使用

Kotlin的物件表示式與Java中的匿名內部類的主要區別:匿名內部類只能指定一個父型別,但物件表示式可以指定0~N個膚型別。

一、物件表示式

物件表示式的語法格式如下:

object [: 0~N個父型別]{
  //物件表示式的類體部分
}

物件表示式還有如下規則:

  • 物件表示式不能是抽象類,因為系統在建立物件表示式時會立即建立物件。因此不允許將物件表示式定義成抽象類。
  • 物件表示式不能定義構造器。但物件表示式可以定義初始化塊,可以通過初始化塊來完成構造器需要完成的事情。
  • 物件表示式可以包含內部類,不能包含巢狀類。
package `0705`

interface Outputable {
  fun output(msg: String)
}

abstract class Product(var price: Double) {
  abstract val name: String
  abstract fun printInfo()
}

fun main(args: Array<String>) {
  //指定一個父型別(介面)的物件表示式
  var ob1 = object : Outputable {
    override fun output(msg: String) {
      for (i in 1..6) {
        println("<h${i}>${msg}</h${i}>")
      }
    }
  }
  ob1.output("隨便輸出點什麼吧")
  println("-----------------------------------------------")
  //指定零個父型別的物件表示式
  var ob2 = object {
    //初始化塊
    init {
      println("初始化塊")
    }

    //屬性
    var name = "Kotlin"

    //方法
    fun test() {
      println("test方法")
    }

    //只能包含內部類,不可以包含巢狀類
    inner class Inner
  }
  println(ob2.name)
  ob2.test()
  println("-----------------------------------------------")
  //指定兩個父型別的物件表示式
  var ob3 = object : Outputable,Product(1.23) {
    override fun output(msg: String) {
      println("輸出資訊:${msg}")
    }

    override val name: String
      get() = "鐳射印表機"

    override fun printInfo() {
      println("高速極光印表機們支援自動雙面列印!")
    }
  }
  println(ob3.name)
  ob3.output("Kotlin慢慢學")
  ob3.printInfo()
}

輸出結果:

<h1>隨便輸出點什麼吧</h1>
<h2>隨便輸出點什麼吧</h2>
<h3>隨便輸出點什麼吧</h3>
<h4>隨便輸出點什麼吧</h4>
<h5>隨便輸出點什麼吧</h5>
<h6>隨便輸出點什麼吧</h6>
-----------------------------------------------
初始化塊
Kotlin
test方法
-----------------------------------------------
鐳射印表機

輸出資訊:Kotlin慢慢學
高速極光印表機們支援自動雙面列印!

Kotlin的物件表示式可分為兩種情形:

  • 物件表示式在方法的區域性範圍內,或使用private修飾的物件表示式,Kotlin編譯器可識別物件表示式的真實型別。
  • 非private修飾的物件表示式與Java的匿名內部類相似,編譯器只會把物件表示式當成它所繼承的父類或所實現的介面處理。如果它沒有父型別,系統當它是Any型別。
package `0705`

class ObjectExprType {
  private val ob1 = object {
    val name: String = "Kotlin"
  }
  internal val ob2 = object {
    val name: String = "Kotlin"
  }
  private fun privateBar()=object {
    val name:String="Java"
  }
  fun publicBar()=object {
    val name:String="Java"
  }
  fun test(){
    //ob1是private物件表示式,編譯器可識別它的真實型別
    println(ob1.name)
    //ob2是非private物件表示式,編譯器當它是Any型別
//    println(ob2.name)
    //privateBar是private函式,編譯器可識別它返回的物件表示式的真實型別
    println(privateBar().name)
    //publicBar是非private函式,編譯器將它返回的物件表示式當成Any型別
//    println(publicBar().name)
  }
}

fun main(args: Array<String>) {
  ObjectExprType().test()
}

輸出結果:

Kotlin
Java

Kotlin編譯器可以識別private物件表示式的真實型別。

Kotlin的物件表示式可訪問或修飾其作用域內的區域性變數。

fun main(args: Array<String>) {
  var a = 20
  var obj = object {

    fun change() {
      println("change()方法修改變數a的值")
      a++
    }
  }
  obj.change()
  println(a)
}

輸出結果:

change()方法修改變數a的值
21

Kotlin的物件表示式比Java的匿名內部類增強了三個方面:

  • 物件表示式可指定多個父型別
  • Kotlin編譯器能更準確地識別區域性範圍內private物件表示式的型別。
  • 物件表示式可訪問或修改其所在範圍內的區域性變數

二、物件宣告和單例模式

物件宣告的語法格式如下:

object ObjectName [: 0~N個父型別]{
  //物件表示式的類體部分
}

物件宣告與物件表示式的語法很相似,區別在於:物件表示式在object關鍵字後沒有名字;而物件宣告需要在object關鍵字後指定名字。

兩者還有如下區別:

  • 物件表示式是一個表示式,可以被賦值給變數;而物件宣告不是表示式,不能用於賦值。
  • 物件宣告可包含巢狀類,不能包含內部類;而物件表示式可包含內部類,不能包含巢狀類。
  • 物件宣告不能定義在函式和方法內;但物件表示式可巢狀在其他物件宣告或非內部類中。
package `0705`

interface Outputable {
  fun output(msg: String)
}

abstract class Product(var price: Double) {
  abstract val name: String
  abstract fun printInfo()
}

//指定一個父型別的物件表示式
object MyObject1 : Outputable {
  override fun output(msg: String) {
    for (i in 1..6) {
      println("<h${i}>${msg}</h${i}>")
    }
  }
}

//指定零個父型別的物件表示式
object MyObject2 {
  //初始化塊
  init {
    println("初始化塊")
  }

  //屬性
  var name = "Kotlin"

  //方法
  fun test() {
    println("test方法")
  }

  //只能包含巢狀類,不可以包含內部類
  class Inner
}

//指定兩個父型別的物件表示式
object MyObject3 : Outputable,Product(1.23) {
  override fun output(msg: String) {
    println("輸出資訊:${msg}")
  }

  override val name: String
    get() = "鐳射印表機"

  override fun printInfo() {
    println("高速極光印表機們支援自動雙面列印!")
  }
}

fun main(args: Array<String>) {

  MyObject1.output("一起來學Kotlin")
  println("-----------------------------------------------")
  println(MyObject2.name)
  MyObject2.test()
  println("-----------------------------------------------")
  println(MyObject3.name)
  MyObject3.output("Kotlin真不錯")
  MyObject3.printInfo()
}

輸出結果:

<h1>一起來學Kotlin</h1>
<h2>一起來學Kotlin</h2>
<h3>一起來學Kotlin</h3>
<h4>一起來學Kotlin</h4>
<h5>一起來學Kotlin</h5>
<h6>一起來學Kotlin</h6>
-----------------------------------------------
初始化塊
Kotlin
test方法
-----------------------------------------------
鐳射印表機
輸出資訊:Kotlin真不錯
高速極光印表機們支援自動雙面列印!

物件宣告專門用於實現單例模式,物件宣告所定義的物件也就是該類的唯一例項,程式可通過物件宣告的名稱直接訪問該類的唯一例項。

三、伴生物件和靜態成員

在類中定義的物件宣告,可使用companion修飾,這樣該物件就變成了伴生物件。

每個類最多隻能定義一個伴生物件,伴生物件相當於外部類的物件,程式可通過外部類直接呼叫伴生物件的成員。

package `0705`

interface CompanionTest {
  fun output(msg: String)
}

class MyClass {
  //使用companion修飾的伴生物件
  companion object MyObject1 : CompanionTest {
    val name = "name屬性值"
    override fun output(msg: String) {
      for (i in 1..6) {
        println("<h${i}>${msg}</h${i}>")
      }
    }
  }
}

fun main(args: Array<String>) {
  //使用伴生物件所在的類呼叫伴生物件的方法
  MyClass.output("Kotlin必須學")
  println(MyClass.name)
}

輸出結果:

<h1>Kotlin必須學</h1>
<h2>Kotlin必須學</h2>
<h3>Kotlin必須學</h3>
<h4>Kotlin必須學</h4>
<h5>Kotlin必須學</h5>
<h6>Kotlin必須學</h6>
name屬性值

伴生物件的主要作用就是為其所在的外部類模擬靜態成員,但只是模擬,伴生物件的成員依然是伴生物件本身的例項成員,並不屬於伴生物件所在的外部類。

四、伴生物件的擴充套件

伴生物件也可以被擴充套件。如果一個類具有伴生物件,則Kotlin允許為伴生物件擴充套件方法和屬性。

package `0705`

interface CompanionTest {
  fun output(msg: String)
}

class MyClass {
  //使用companion修飾的伴生物件
  companion object : CompanionTest {
    val name = "name屬性值"
    override fun output(msg: String) {
      for (i in 1..6) {
        println("<h${i}>${msg}</h${i}>")
      }
    }
  }
}

//為伴生物件擴充套件方法
fun MyClass.Companion.test() {
  println("為伴生物件擴充套件的方法")
}

val MyClass.Companion.foo
  get() = "為伴生物件擴充套件的屬性"

fun main(args: Array<String>) {
  //使用伴生物件所在的類呼叫伴生物件的方法
  MyClass.output("Kotlin必須學")
  println(MyClass.name)
  //通過伴生物件所在的類呼叫為伴生物件擴充套件的成員
  MyClass.test()
  println(MyClass.foo)

}

輸出結果:

<h1>Kotlin必須學</h1>
<h2>Kotlin必須學</h2>
<h3>Kotlin必須學</h3>
<h4>Kotlin必須學</h4>
<h5>Kotlin必須學</h5>
<h6>Kotlin必須學</h6>
name屬性值
為伴生物件擴充套件的方法
為伴生物件擴充套件的屬性

以上就是本文的全部內容,希望對大家的學習有所幫助,也希望大家多多支援我們。