object關(guān)鍵字在多種情況下出現(xiàn),其核心理念:將聲明一個類和創(chuàng)建一個實例結(jié)合起來。class
使用場景:
1、對象聲明是定義單例的一種方式。
2、伴生對象可以持有工廠方法和其他與這個類有關(guān)。但在調(diào)用時并不依賴類實例的方法。他們的成員可以通過類名來訪問。
3、對象表達(dá)式用來代替Java的匿名內(nèi)部類。
1.1、對象聲明:創(chuàng)建單例易如反掌
Kotlin通過使用對象聲明功能將類的聲明與該類的單一實例聲明結(jié)合到了一起。
object? Payroll{
?????? val allEmployees=arrayListOf<Person>()
??????? fun calculateSalary(){
???????????????? for(person in allEmployees){...}
??????? }
}
對象聲明唯一不允許的就是構(gòu)造方法,包括朱構(gòu)造方法和從構(gòu)造方法。
調(diào)用:Payroll.allEmployees.add(Person(...))
Payroll.calculateSalary()
對象聲明同樣可以繼承自類和接口。通常在你使用的框架需要趨勢線一個接口,但是你的實現(xiàn)并不包含任何狀態(tài)的時候很有用。例如Comparator接口。
1.2、伴生對象:工廠方法和靜態(tài)成員的地盤
Kotlin中的類不能擁有靜態(tài)成員,它沒有static關(guān)鍵字。包級別函數(shù)(多頂層函數(shù)) 可以替代 Java靜態(tài)的方法 ;對象聲明 可以替代? Java靜態(tài)方法 和 靜態(tài)字段。頂層函數(shù)不能訪問類的private成員,可以使用 那個類中的對象聲明的成員。
在類中定義的對象之一可以使用一個特殊的關(guān)鍵字來標(biāo)記:companion 。這樣可以直接通過容器類名稱來訪問這個對象的方法和屬性。
class?? A {
????????? companion? object {
????????????????? fun bar() = println(" Companion? object?? called ")
???????? }
}
調(diào)用:A.bar()?
class User {???? //一般我們會用多個構(gòu)造來創(chuàng)建不同的對象
????? val? nickname : String
????? constructor(email:String){
???????????????? nickname=email.substringBefore('@')
?????? }
?????? constructor(facebookAccountId:Int){
????????????????? nickname=getFacebookName(facebookAccountId)
??????? }
??????? private fun getFacebookName(facebookAccountId: Int): String {
???????????????? return "facebookUserName"
? ???? }
}
//使用工廠方法來代替從構(gòu)造方法
class Userprivate constructor(val nickname : String){
private val niname ="bob" // 在companion object 內(nèi)無法訪問
? ? companion object {
?????????? ? fun newSubscribingUser(email: String) = User(email.substringBefore('@'))
???????????? fun newFacebookUser(accountId : Int) = User(getFacebookName(accountId))
???????????? private fun getFacebookName(accountId: Int): String {
??????????????????????? return "facebookUserName"
? ? ? ?????? }
??? }
}
優(yōu)點:工廠方法可以返回聲明這個方法的類的子類(如newSubscribingUser,newFacebookUser類都是User的子類)
缺點:如果要擴(kuò)展這樣的類,使用多構(gòu)造方法更好,因為伴生對象成員在子類中不能被重寫。
1.3、作為普通對象使用的伴生對象
1.3.1、聲明一個命名伴生對象
class Person(val name :String){
???????? companion object Loader{????? //聲明一個命名伴生對象
???????????????? fun fromJson(jsonText:String):Person = Person(jsonText)
????????? }
}
1.3.2、在伴生對象中實現(xiàn)接口
interface JSONFactory{
??????? fun fromJSON(jsonText: String):T
}
class Person(val name :String){
?????????? companion object : JSONFactory{
???????????????????? override fun fromJSON(jsonText: String): Person { //實現(xiàn)接口的伴生對象
????????????????????????????? return Person(jsonText)
????????????????????? }
??????????? }
}
1.3.3、伴生對象的擴(kuò)展
class? Person(val firstName : String,val lastName :String){
???????? companion?? object {?? //空的伴生對象
??????? }
}
fun? Person.Companion.fromJson(json;String) :Person{} //聲明擴(kuò)展函數(shù)
val? p=Person.fromJson(json)? //調(diào)用
1.4、對象表達(dá)式:改變寫法的匿名內(nèi)部類
object關(guān)鍵字還可以用來聲明匿名對象。
window.addMouseListener (
?????????? object:MouseAdapter(){?? //聲明繼承MouseAdapter的匿名對象
?????????????????? override? fun? mouseClicked(e:MouseEvent){}
?????????????????? override? fun? mouseEntered(e:MouseEvent){}
????????? }
)
與對象聲明不同,匿名對象不是單例的。每次對象表達(dá)式被執(zhí)行都會創(chuàng)建一個新的對象實例。
擴(kuò)展函數(shù)我的通俗理解:類名.方法名? 的方法 稱之為擴(kuò)展函數(shù)。
fun? countClicks(window:Window){
??????? var clickCount= 0
???????? window.addMouseListener(
??????????????? object:MouseAdapter(){?? //聲明繼承MouseAdapter的匿名對象
???????????????????? override? fun? mouseClicked(e:MouseEvent){clickCount ++ } //匿名對象訪問局部變量
????????????????????? override? fun? mouseEntered(e:MouseEvent){}
??????????? }
????? )
}