
前言
本文章只是用于記錄學習,所以部分地方如果有錯誤或者理解不對的地方,麻煩請指正。本篇為 csdn 原文章 轉(zhuǎn)移修改版 原文章
??Java中,不管是為了實現(xiàn)接口,或者是抽象類,我們總是習慣使用匿名內(nèi)部類。最熟悉的例子,莫過于對單擊事件的監(jiān)聽.
btn.setOnClickListener(new OnClickListener{
// 處理單擊事件邏輯
});
??Kotlin沒有匿名內(nèi)部類,恰巧其用object一個簡單的關鍵字,解決了這一個問題,我們一起來學習下。
對象表達式
對象表達式更傾向于表達式這一點,針對 java 中點擊事件的使用,我們演示下再kotlin 中如何編寫
btn.setOnClickListener(object : OnClickListener{
});
??對象表達式內(nèi)的代碼可以訪問創(chuàng)建這個對象的代碼范圍內(nèi)的變量,與Java不同的是,被訪問的變量不需要被限制為final變量(挺爽的)。
var a = 10
val listener = object {
fun doClick() {
println("a:$a")
}
}
listener.doClick() // 打印 a:10
??當然我們也可以只是用對象
val adHoc = object {
var x: Int = 0
var y: Int = 0
}
print(adHoc.x + adHoc.y)
??接下來我們看一下 對象在繼承實現(xiàn)方面的使用
open class A(x: Int) {
public open val y: Int = x
}
interface B {……}
val ab: A = object : A(1), B {
override val y = 15
}
??如果超類型有一個構造函數(shù),則必須傳遞參數(shù)給它。多個超類型和接口可以用逗號分隔。
請注意,匿名對象可以用作只在本地和私有作用域中聲明的類型。如果你使用匿名對象作為公有函數(shù)的 返回類型或者用作公有屬性的類型,那么該函數(shù)或?qū)傩缘膶嶋H類型 會是匿名對象聲明的超類型,如果你沒有聲明任何超類型,就會是 Any。在匿名對象 中添加的成員將無法訪問
class C {
// 私有函數(shù),所以其返回類型是匿名對象類型
private fun foo() = object {
val x: String = "x"
}
// 公有函數(shù),所以其返回類型是 Any
fun publicFoo() = object {
val x: String = "x"
}
fun bar() {
val x1 = foo().x // 沒問題
val x2 = publicFoo().x // 錯誤:未能解析的引用“x”
}
}
2. 對象聲明
??所謂的對象聲明,我們可以理解為 java 中的單例模式。
object Site {
var url:String = ""
val name: String = "ymc"
}
fun main(args: Array<String>) {
var s1 = Site
var s2 = Site
s1.url = "www.google.com"
println(s1.url)
println(s2.url)
}
輸出結果
www.google.com
www.google.com
??可以看到,object 指向的對象是同一個。
與對象表達式不同,當對象聲明在另一個類的內(nèi)部時,這個對象并不能通過外部類的實例訪問到該對象,而只能通過類名來訪問
同樣該對象也不能直接訪問到外部類的方法和變量。
class ObjectDemo {
var objName = "菜鳥教程"
object DeskTop{
var url = "www.runoob.com"
fun showName(){
print{"desk legs $objName"} // 錯誤,不能訪問到外部類的方法和變量
}
}
}
fun main(args: Array<String>) {
ObjectDemo.DeskTop.url //只能通過類名 訪問到,而不能通過實例
val obj = ObjectDemo()
obj.objName // 通過實例 不能訪問到 ObjectDemo 對象
}
3. 伴生對象
??類內(nèi)部的對象聲明可以用 companion 關鍵字標記,這樣它就與外部類關聯(lián)在一起,我們就可以直接通過外部類訪問到對象的內(nèi)部元素。當然我們也可以省略對象的對象名,使用 Companion 來代替
class MyClass {
companion object Factory {
fun create(): MyClass = MyClass()
}
}
val instance = MyClass.create() // 訪問到對象的內(nèi)部元素
--------------------------
// 也可以這樣寫
class MyClass {
companion object {
}
}
val x = MyClass.Companion //直接使用 companion 代替
注意:一個類里面只能聲明一個內(nèi)部關聯(lián)對象,即關鍵字 companion 只能使用一次。
請伴生對象的成員看起來像其他語言的靜態(tài)成員,但在運行時他們?nèi)匀皇钦鎸崒ο蟮膶嵗蓡T。例如還可以實現(xiàn)接口:
interface Factory<T> {
fun create(): T
}
class MyClass {
companion object : Factory<MyClass> {
override fun create() : MyClass{
return MyClass()
}
}
}