1.什么是object關(guān)鍵字
Kotlobject關(guān)鍵字在多種情況下出現(xiàn),但是它都遵循同樣的核理念,這個關(guān)鍵字定義一個類并同時創(chuàng)建個實例(也就是一個類對象)
2.object關(guān)鍵字在kotlin中的用例
2.1對象聲明
java中使用單例模式,需要三步: 私有化構(gòu)造方法,創(chuàng)建一個該類的實例,提供一個獲取該實例的方法.而在kotlin中只需要object一個關(guān)鍵字即可.對,就是這么簡單!用object關(guān)鍵字進行對象聲明后,就可以用類名.方法 的方式調(diào)用方法.這也印證了定義中說明的聲明一個類,同時聲明該類的一個實例.
示例代碼如下:
object ObjectKeyTest {
override fun toString(): String {
return "我是一個ObjectKeyTest"
}
}
fun main(args: Array) {
println(ObjectKeyTest.toString())
}
對象聲明一樣可以繼承類和接口,這個一般在你的實現(xiàn)并不包含任何實現(xiàn)的時候很有用.例如你實現(xiàn)一個比較器的接口用于比較:
object FilePathComparator : Comparator<File> {
override fun compare(file1 : File, file2: File): Int {
return file1.path!!.compareTo(file2.path)
}
}
fun main(args: Array<String>) {
println(FilePathComparator.compare(File("/User"),File("/user")))
}
同樣,可以在類中使用聲明對象,這樣的對象在類中也是單一實例存在的,kotlin中可以理解成一個類中的單一實例,不隨宿主類對象的不同而變化.這種類中嵌套一個類,用object關(guān)鍵字聲明時一樣可以用類名.對象的方法,用法如下:
class FileUtils {
object FilePathComparator : Comparator<File> {
override fun compare(file1: File, file2: File): Int {
return file1.path!!.compareTo(file2.path)
}
}
}
fun main(args: Array<String>) {
val fileUtils : FileUtils = FileUtils()
FileUtils.FilePathComparator
println(FileUtils.FilePathComparator.compare(File("/User"),File("/user")))
}
2.2使用object聲明伴生對象
在kotlin沒有static關(guān)鍵字的概念,假如要使用靜態(tài)方法怎么辦呢?那么可以使用伴生對象,或者使用頂層函數(shù),不過,頂層函數(shù)不能訪問類中的私有成員,但伴生對象可以,用法如下:
class CompanionTest {
private val string = "伴生對象可以訪問我"
companion object {
fun printStr() {
println(CompanionTest().string)
}
}
}
fun main(args: Array<String>) {
CompanionTest.printStr()
}
如上所示,string作為一個私有變量,伴生對象是有訪問權(quán)限的.但是這里要注意,直接訪問string這個類成員是不可以的,因為伴生對象的方法相當(dāng)于一個static靜態(tài)方法,而string是非靜態(tài)的,所以要先創(chuàng)建對象才能訪問.
伴生對象在工廠方法中使用是其一個很好的實踐,可以替代多構(gòu)造方法的構(gòu)造函數(shù),例如有如下示例:
class UserBean {
var nickName : String
constructor(id : Int) {
nickName = "$id"
}
constructor(email : String) {
nickName = email.plus("*")
}
}
然后使用伴生對象創(chuàng)建工廠方法,并且把構(gòu)造方法變成私有,示例如下:
//構(gòu)造方法標(biāo)記為私有,防止外部調(diào)用
class UserBean1 private constructor(val userName : String){
companion object {
fun newIdUser(id : Int) = UserBean1("$id")
fun newEmailUser(email : String) = UserBean1(email.plus("abc"))
}
}
fun main(args: Array<String>) {
var User1 = UserBean1.newIdUser(1)
var User2 = UserBean1.newEmailUser("abc@sina.com")
}
如果需要創(chuàng)建不同的對象,可以使用上面的工廠方法創(chuàng)建,但是這里要注意,伴生對象是不可以重寫的,如果需要擴展,還是采用多構(gòu)造方法比較好.
同時伴生對象還可以有名字:
class UserBean2 {
companion object Loader {
fun getData() : String {
return "userbean2"
}
}
}
fun main(args: Array<String>) {
println(UserBean2.getData())
}
伴生對象還可以實現(xiàn)接口:
interface Loader {
fun getData() : String
}
class UserBean3 {
companion object MyLoader : Loader {
override fun getData() : String {
return "userbean3"
}
}
}
fun main(args: Array<String>) {
println(UserBean3.getData())
}
還可以直接將類名當(dāng)昨?qū)ο螽?dāng)做該接口的實現(xiàn)對象進行傳遞
interface Loader {
fun getData() : String
}
class UserBean3 {
companion object MyLoader : Loader {
override fun getData() : String {
return "userbean3"
}
}
}
fun loadUserData(loader: Loader) {
println(loader.getData())
}
fun main(args: Array<String>) {
loadUserData(UserBean3)
}
你還可以為伴生對象定義擴展函數(shù),因為有時你想將某些數(shù)據(jù)處理與原類的核心邏輯分離,這個時候可以使用擴展函數(shù),而伴生對象也支持?jǐn)U展函數(shù).
先定義一個伴生對象:
class UserBean4 {
//聲明一個空的伴生對象,為定義擴展函數(shù)做準(zhǔn)備
companion object {
}
}
再為該對象定義擴展函數(shù):
//注意這里沒有定義伴生對象名稱,直接用Companion引用
fun UserBean4.Companion.getType() : String {
return "UserName4"
}
fun main(args: Array<String>) {
val data = UserBean4.getType()
println(data)
}
object關(guān)鍵字還可以用來聲明匿名內(nèi)部類,kotlin中用匿名對象的方式代替了java中的匿名內(nèi)部類的使用方式,并且,該匿名內(nèi)部類不像java只能實現(xiàn)一個接口或繼承一個對象,它可以實現(xiàn)多個接口,用法如下:
interface MyInterface1 {
fun getSomething()
}
interface MyInterface2 {
fun doSomething()
}
fun doing(myInterface1: MyInterface1) {
myInterface1.getSomething()
}
fun main(args: Array<String>) {
doing(object : MyInterface1,MyInterface2 {
override fun getSomething() {
}
override fun doSomething() {
}
})
}
同時,它還可以有名字,也就是像Java一樣定義成一個成員:
fun main(args: Array<String>) {
doing(MyInterfaceImpl)
}
val MyInterfaceImpl = object : MyInterface1 {
override fun getSomething() {
}
}
它還可以訪問外部函數(shù)創(chuàng)建的變量,并且不用標(biāo)識為final類型:
class MyTest {
fun main(args: Array<String>) {
var count : Int = 0
doing(object : MyInterface1 {
override fun getSomething() {
val arg0 = args[0]
count ++
}
})
}
}