<ruby id="bdb3f"></ruby>

    <p id="bdb3f"><cite id="bdb3f"></cite></p>

      <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
        <p id="bdb3f"><cite id="bdb3f"></cite></p>

          <pre id="bdb3f"></pre>
          <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

          <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
          <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

          <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                <ruby id="bdb3f"></ruby>

                合規國際互聯網加速 OSASE為企業客戶提供高速穩定SD-WAN國際加速解決方案。 廣告
                # 對象表達式與對象聲明 [TOC] 有時候,我們**需要創建一個對某個類做了輕微改動的類的對象,而不用為之顯式聲明新的子類。Kotlin 用對象表達式和對象聲明處理這種情況**。 * 對象表達式(object expressions), * 對象聲明(object declarations), * 伴生對象(companion object) ## 對象表達式(object expressions) 要創建一個繼承自某個(或某些)類型的匿名類的對象,我們會這么寫: ```kotlin window.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { /*……*/ } override fun mouseEntered(e: MouseEvent) { /*……*/ } }) ``` ### 定義: 如果超類型(父類,比如接口,抽象類,可繼承的一般類)有一個構造函數,則必須傳遞適當的構造函數參數給它。多個超類型可以由跟在冒號后面的逗號分隔的列表指定: ```kotlin open class A(x: Int) { public open val y: Int = x } interface B { /*……*/ } // A(1) 子類必須傳遞參數給父類的構造函數 val ab: A = object : A(1), B {//這就是對象表達式 override val y = 15 } ``` 任何時候,如果我們**只需要“一個對象而已”,并不需要特殊超類型**,那么我們可以簡單地寫: ```kotlin fun foo() { val adHoc = object { var x: Int = 0 var y: Int = 0 } print(adHoc.x + adHoc.y) } ``` ### 作用域:訪問權限 #### 外部訪問內部 >[success]請注意,**匿名對象可以用作只在本地和私有作用域中聲明的類型**。如果你使用匿名對象作為公有函數的返回類型或者用作公有屬性的類型,那么該函數或屬性的實際類型會是匿名對象聲明的超類型(父類型),如果你沒有聲明任何超類型,就會是 `Any`(沒有父類,就是Any)。無法訪問匿名對象的成員(在匿名對象中添加的成員將無法訪問)。 ```kotlin class C { // 私有函數,所以其返回類型是匿名對象類型 private fun foo() = object { val x: String = "x" } // 默認是公有函數,所以其返回類型是 Any fun publicFoo() = object { val x: String = "x" } fun bar() { val x1 = foo().x // 正確: 類型是object{..},可以訪問x val x2 = publicFoo().x // 錯誤: 類型是Any,無法訪問x } } ``` #### 內部訪問外部 像Java匿名內部類一樣,對象表達式可訪問<包含它的作用域> 對象表達式中的代碼可以訪問來自包含它的作用域的變量。 ```kotlin fun countClicks(window: JComponent) { var clickCount = 0 var enterCount = 0 window.addMouseListener(object : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { clickCount++ } override fun mouseEntered(e: MouseEvent) { enterCount++ } }) // …… } ``` ## 對象聲明/單例模式(object declarations) 單例模式在一些場景中很有用,而 Kotlin(繼 Scala 之后)使單例聲明變得很容易: ```kotlin //定義單例對象(對象聲明) object DataProviderManager { fun registerDataProvider(provider: DataProvider) { // …… } val allDataProviders: Collection<DataProvider> get() = // …… } ``` 這稱為**對象聲明**。并且它總是在 **object**關鍵字后跟一個名稱。 * 就像變量聲明一樣,**對象聲明不是一個表達式,不能用在賦值語句的右邊**。 * **對象聲明的初始化過程是線程安全的**。 * 如需引用該對象,我們直接使用其名稱即可: ```kotlin //使用單例對象 DataProviderManager.allDataProviders DataProviderManager.registerDataProvider(……) ``` 這些對象可以有超類型: ```kotlin //單例對象繼承超類(父類) object DefaultListener : MouseAdapter() { override fun mouseClicked(e: MouseEvent) { …… } override fun mouseEntered(e: MouseEvent) { …… } } ``` >[warning]**注意**:對象聲明不能在局部作用域(即直接嵌套在函數內部),但是它們可以嵌套到其他對象聲明或非內部類中。 ## 伴生對象(companion object) * 1、類內部的伴生對象聲明可以用 **companion**關鍵字標記,類似于Java類的static靜態成員: ```kotlin class MyClass { companion object Factory {//Factory就是MyClass的伴生對象 fun create(): MyClass = MyClass() } } ``` ~~~ 伴隨對象的調用不用創建包含伴隨對象的實例,調用方式有兩種, 一種是類名.伴隨對象.XX,另外一種方式是類名.xx ~~~ * 2、該伴生對象的成員可通過只使用類名作為限定符來調用: ```kotlin val instance = MyClass.create() ``` * 3、可以省略伴生對象的名稱,在這種情況下將使用名稱 `Companion`: ```kotlin class MyClass { //可省略伴生對象名 companion object { } } val x = MyClass.Companion ``` 其自身所用的類的名稱(不是另一個名稱的限定符)可用作對該類的伴生對象(無論是否命名)的引用: ```kotlin class MyClass1 { companion object Named { } } val x = MyClass1 //可省略伴生對象名 class MyClass2 { companion object { } } val y = MyClass2 ``` * 一個類只有一個伴生對象,伴生對象所在的類被加載,伴生對象被初始化,與Java靜態成員一樣。 示例: ~~~ class MyClass { companion object Obj { val a = 1 fun crt(): MyClass = MyClass() } val b = 2 } //直接類名調用伴生對象(類似于Java的靜態成員) fun main(args: Array<String>) { println(MyClass.a) //輸出1 println(MyClass.Obj.a) //輸出1 println(MyClass.crt().b) //輸出2 println(MyClass.Obj.crt().b) //輸出2 } ~~~ >[danger]請注意,即使伴生對象的成員看起來像其他語言的靜態成員,**在運行時他們仍然是真實對象的實例成員**,而且,例如還可以實現接口: ```kotlin interface Factory<T> { fun create(): T } class MyClass { companion object : Factory<MyClass> { override fun create(): MyClass = MyClass() } } val f: Factory<MyClass> = MyClass ``` 當然,在 JVM 平臺,如果使用 `@JvmStatic` 注解,你可以將伴生對象的成員生成為真正的靜態方法和字段。更詳細信息請參見[Java 互操作性](http://www.hmoore.net/alex_wsc/android_kotlin/1318356)一節。 ### 對象表達式和對象聲明之間的語義差異 對象表達式和對象聲明之間有一個重要的語義差別: * 對象表達式是在使用他們的地方**立即**執行(及初始化)的; * 對象聲明是在第一次被訪問到時**延遲**初始化的; * 伴生對象的初始化是在相應的類被加載(解析)時,與 Java 靜態初始化器的語義相匹配。
                  <ruby id="bdb3f"></ruby>

                  <p id="bdb3f"><cite id="bdb3f"></cite></p>

                    <p id="bdb3f"><cite id="bdb3f"><th id="bdb3f"></th></cite></p><p id="bdb3f"></p>
                      <p id="bdb3f"><cite id="bdb3f"></cite></p>

                        <pre id="bdb3f"></pre>
                        <pre id="bdb3f"><del id="bdb3f"><thead id="bdb3f"></thead></del></pre>

                        <ruby id="bdb3f"><mark id="bdb3f"></mark></ruby><ruby id="bdb3f"></ruby>
                        <pre id="bdb3f"><pre id="bdb3f"><mark id="bdb3f"></mark></pre></pre><output id="bdb3f"></output><p id="bdb3f"></p><p id="bdb3f"></p>

                        <pre id="bdb3f"><del id="bdb3f"><progress id="bdb3f"></progress></del></pre>

                              <ruby id="bdb3f"></ruby>

                              哎呀哎呀视频在线观看