1. 程式人生 > >kotlin筆記 第八章 (六)物件表示式、物件宣告與伴生物件.md

kotlin筆記 第八章 (六)物件表示式、物件宣告與伴生物件.md

如果物件是函式式介面(只有一個抽象方法的介面),則可以使用帶介面類字首的Lambda表示式建立物件,如:Runnable

	Var r=Runnable{

		......(run()方法實現)

	}

1、物件表示式

物件表示式成員:初始化塊、屬性、方法、內部類(不能包含巢狀類),不能有構造器

物件表示式相當於Java中的匿名內部類,但功能更強大:

  1. 物件表示式可以只用指定父型別,也可以有一個或多個父型別

語法格式:

object[:0-N個父型別(父類類、介面)]{

	初始化塊
	屬性
	方法
	內部類,不能包含巢狀類
	



}
  1. 物件表示式不能是抽象類,系統在建立物件表示式時就會立即建立物件,因此不允許將物件表示式定義為抽象類
  2. 物件表示式不能定義構造器,但可以有初始化塊
  3. 物件表示式可以包含內部類,不能包含巢狀類

Kotlin中表達式:

  1. 表示式在區域性範圍內(函式或者方法中)或者使用private修飾物件表示式,Kotlin編譯器可以識別物件表示式的真實型別;比如: fun main(args:Array){ var obj=object { var name=“leslie” fun test(){

     	}
    
    
     }
    

    var obj2=object:outputable { var name=“leslie” fun test(){

     		}
     	override fun output(msg:String){
    
     	}
    
    
     	}
    

    }

這裡編譯器是可以識別obj變數的型別的,因此也就可以呼叫其變數以及方法,無論是從父類、既可重寫的方法還是自己新增的方法、屬性

  1. ***(作為成員變數)***非private修飾的物件表示式就和Java中的匿名內部類一樣了,編譯器只會把該物件表示式當成他父類(介面)處理,不能識別器真實型別,如果物件表示式沒有父類,就當成Any類處理,自然物件表示式中新增的屬性、方法就呼叫不到,只能呼叫繼承、重寫的方法、屬性

    class Sub{ //1、private修飾的物件表示式 private var obj={ var name:String=“leslie”

     	override fun test(mas:String){
    
    
     		}
    
     }
    
     //2、非private
     internal var obj2=object:Outputable{
     	var name:String="leslie"
    
     	override fun test(mas:String){
    
    
     		}
    
     	}
    
     //3、(單表示式函式),物件表示式作為函式返回值
     private fun say()=object:Outputable{
     	var name:String="leslie"
    
     	override fun test(mas:String){
    
    
     		}
    
     	}
    

    //4、(單表示式函式),物件表示式作為函式返回值 internal fun say()=object:Outputable{ var name:String=“leslie”

     	override fun test(mas:String){
    
    
     		}
    
     	}
    

    } 第一和第三種情況由於能識別變數真實型別呼叫其name屬性(obj.name、say().name)自然沒有問題,而第二種和第四種情況不能識別其真實型別,只能當做父型別處理,編譯期型別即為父型別,由於沒有name屬性,自然報錯;

還有一點就是:java中要求匿名內部類訪問區域性變數時,區域性變數必須final修飾,就是說該區域性變數不能別被修改,而Kotlin中可以修改該區域性變數;

2、物件宣告

其作用就是實現單例模式;

語法

object 物件宣告名稱[:0-N個父型別]{
	//定義屬性
	//方法
	//巢狀類,不能定義內部類(非靜態內部類)
	//初始化塊


	}

物件宣告和物件表示式語法大體格式都一樣,也有一些區別:

  1. 物件表示式是一個表示式(可以看做一個物件),可以被賦值給變數,而物件宣告不是表示式,不能用於賦值
  2. 物件宣告可以包含巢狀類,但不能包含內部類;而物件表示式只能包含內部類而不能包含巢狀類 3.*** 物件宣告不能定義在函式或方法內,但物件表;達式可巢狀在其他物件宣告中或非內部類中***

物件宣告定義位置

  1. 在kotlin檔案中定義物件宣告:

    interface Outputable{ fun output(msg:String) }

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

    object MyObj1:Outputable{ override fun output(msg: String) { Log.d(“TAG”,“重寫從父類繼承到的方法”) }

    }

    object MyObj2{ init { Log.d(“TAG”,“初始化塊”) } var name=“Kotlin” fun test(){ Log.d(“TAG”,“test方法”) } class Foo

    }

呼叫:MyObj1.output(“輸出裝置”)

  1. 在類體中定義

     class ObjectDecl{
    
        object  MyObj3{
             init {
                 Log.d("TAG","定義在類體中的物件宣告的初始塊")
             }
           var name:String="leslie"
           class Foo
           fun info(){
               Log.d("TAG","定義在類體中的物件宣告的方法")
           }
     
         }
    
    
     }
    

物件宣告所定義的物件時該類的唯一例項,通過物件宣告的名稱直接訪問該類的唯一例項;

MyObj1.output(“輸出裝置”)

在類中定義物件宣告

伴生物件

在類中定義物件宣告,使用"conpanion"修飾符,這樣物件就變成了伴生物件;

伴生物件作用:就是為外部類提供靜態屬性、靜態方法,彌補kotlin沒有靜態成員的不足(巢狀類可以看做外部類的靜態成員),物件宣告中的方法、屬性就可看做外部類的靜態屬性、靜態方法

  1. 一個類最多隻能定義一個伴生物件,半身物件就相當於外部類的物件,可以直接通過外部類直接呼叫伴生物件的成員;
  2. 伴生物件的名稱可以省略,如果省略後,要訪問伴生物件,就通過Companion名稱訪問伴生物件即:外部類.Companion;那伴生物件可以訪問了,訪問伴生物件的方法、屬性也就輕而易舉了,即:外部類.Companion.屬性/方法

語法:

	companion object 伴生物件名稱:(0-N)父型別{

	//定義屬性
	//方法
	//巢狀類,不能定義內部類(非靜態內部類)
	//初始化塊

	}

如:

	interface  Outputable{
    fun output(msg:String)
}



	class MyClass{
    companion object MyObj3:Outputable {
            //伴生物件中屬性相當於外部類靜態成員變數
        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("leslie")
    println(MyClass.name)
}

Kotlin中取消了static修飾符,伴生物件就是Kotlin彌補中沒有靜態成員的不足;從上面的例子可以看出伴生物件中的屬性、方法分別相當於外部類的靜態變數、靜態方法.

注意:這裡Kotlin只是利用伴生模擬java中靜態成員,但伴生物件的屬性、方法依然是伴生物件的例項成員,並不屬於伴生物件所在的外部類;

伴生物件擴充套件方法

如果一個類具有伴生物件,允許為伴生物件擴充套件方法和屬性,而為伴生物件擴充套件方法和屬性,就就相當於為外部類擴充套件靜態變數、靜態方法