Java & Groovy & Scala & Kotlin - 18.Object 類 (Scala, Kotlin)

Scala 篇

單例對象

在 Java 中實現(xiàn)單例對象通常需要自己實現(xiàn)一個類并創(chuàng)建 getInstance() 的方法然后在該方法里使用兩次同步塊或者使用更為優(yōu)雅的基于 enum 的方式。而 Scala 中則更加簡單汉操,只要使用 object 聲明就能創(chuàng)建一個單例對象投队。實際上之前我們創(chuàng)建的擁有 main() 方法的都是單例對象合陵。

object Singleton {
  private var num = 0
  def sequence() = {
    num += 1
    num
  }
}

在方法的章節(jié)我們已經(jīng)知道了在 Scala 中是沒有靜態(tài)成員這一說的烛缔,但是有時我們可能又真的需要有這種機制灰殴。Scala 就是采用了使用單例對象來實現(xiàn)類似的靜態(tài)成員霉咨。

例:

assert(1 == Singleton.sequence())
assert(2 == Singleton.sequence())
assert(3 == Singleton.sequence())

可以看到這種方式和在 Java 中調(diào)用靜態(tài)方法一模一樣污秆,但是 Scala 中這其實是調(diào)用了一個對象的方法。

通常來說墅茉,Scala 中的單例對象一般用于提供常量及共享不可變對象命黔。

伴生對象

我們知道使用 class 可以創(chuàng)建一個類,使用 object 可以創(chuàng)建一個單例對象就斤,而類和單例對象是可以重名的悍募,此時我們稱該單例對象為此類的伴生對象。

伴生對象有以下特點

  • 伴生對象可以用于讓一個類即擁有實例化方法又有靜態(tài)方法洋机。
  • 伴生對象可以用于創(chuàng)建同名類的實例坠宴。
  • 伴生對象必須與同名類位于同一源文件中。
  • 伴生對象與類可以互相訪問各自的私有成員绷旗。

例:

創(chuàng)建一個類

class Companion(private var balance: Int = 0) {
  val id = Companion.sequence()
}

創(chuàng)建該類的伴生對象

object Companion {
  private var num = 0

  def getInfo(account: Companion): String = {
    "Balance is " + account.balance
  }

  private def sequence(): Int = {
    num += 1
    num
  }

  def apply(initBalance: Int) = {
    new Companion(initBalance)
  }
}

使用類與伴生對象

//  通過伴生對象的 apply() 方法創(chuàng)建類的實例
val account = Companion(30)

//  在類中調(diào)用伴生對象的私有方法
assert(1 == account.id)

//  在伴生對象中訪問類的私有屬性
assert("Balance is 30" == Companion.getInfo(account))

繼承

單例對象不能繼承另一個單例對象喜鼓,但是單例對象本身可以繼承另一個類,從而擴展該類的功能衔肢,實現(xiàn)該類的可共享的默認對象

例:

abstract class UndoableAction(val description: String) {
  def undo

  def redo
}

object DoNothing extends UndoableAction("Do nothing") {

  override def undo: Unit = {
    println("undo")
  }

  override def redo: Unit = {
    println("redo")
  }

}

以上 DoNothing 繼承了 UndoableAction 類颠通,可以用于作為 UndoableAction 的一個默認對象來使用。

應用程序對象

應用程序對象是繼承類 App 的單例對象膀懈,該對象是一個應用程序的入口顿锰,可以通過 args 獲得命令行參數(shù)。即使用了應用程序對象后你就不需要顯示聲明 main() 方法了启搂,應用程序對象中定義的所有語句都會在 main() 方法中執(zhí)行硼控。

例:

object Hello extends App {

  println("Hello World")

  if (args.length > 0) {
    println("The passed arguments are " + args)
  } else {
    println("There is no argument passed.")
  }
}

Kotlin 篇

Object

Kotlin 中的 Object 用法類似 Scala,但與 Scala 中的 Object 的最大區(qū)別是 Kotlin 不允許 Object 和類同名胳赌。

單例對象

例:

object Singleton {
    private var num = 0

    fun sequence(): Int {
        num += 1
        return num
    }
}

同 Scala 一樣牢撼,Kotlin 也通過 Object 來實現(xiàn)靜態(tài)方法的功能。

例:

assert(1 == Singleton.sequence())
assert(2 == Singleton.sequence())
assert(3 == Singleton.sequence())

伴生對象

伴生對象的概念與 Scala 基本一致疑苫,但是 Kotlin 的伴生對象是通過關鍵字 companion object 定義在類中熏版,而不是類外,伴生對象不與類同名捍掺。

例:

創(chuàng)建類和伴生對象

class Companion(private var balance: Int = 0) {
    //  Access private method of companion object
    val id = Companion.sequence()

    companion object Factory {
        private var num = 0

        fun getInfo(account: Companion): String {
            return "Balance is " + account.balance
        }

        fun create(initBalance: Int): Companion {
            return Companion(initBalance)
        }

        private fun sequence(): Int {
            num += 1
            return num
        }
    }
}

使用類與伴生對象

//  通過伴生對象的方法創(chuàng)建類的實例
val account = Companion.create(30)

//  在類中調(diào)用伴生對象的私有方法
assert(1 == account.id)

//  在伴生對象中訪問類的私有屬性
assert("Balance is 30" == Companion.getInfo(account))

object 表達式

object 表達式用于擴展類的功能撼短,使用時類似 Java 中的匿名內(nèi)部類。

例:

定義一個類和接口

open class A(x: Int) {
    public open val y: Int = x
}

interface B {
    fun info()
}

使用 object 表達式擴展類和接口

val ab = object : A(1), B {
    override fun info() {
        println("info")
    }

    override val y: Int
        get() = 15
}
println(ab.y)
println(ab.javaClass)

以上示例本質上是生成了一個實現(xiàn)類和接口的匿名內(nèi)部類的對象挺勿。在 Kotlin 中也可以不指定任何父類曲横,直接產(chǎn)生匿名內(nèi)部類:

val obj = object {
    val x = 10
    val y = 20
}
println(obj.x)
println(obj.javaClass)

總結

  • Scala 和 Kotlin 使用單例對象來提供其它語言中的全局常量和靜態(tài)方法的特性
  • Scala 的伴生對象與類同名且平級,Kotlin 的伴生對象定義在類中且不同名
  • Kotlin 的 object 表達式可以實現(xiàn)簡單的繼承功能

文章源碼見 https://github.com/SidneyXu/JGSK 倉庫的 scala/_18_objectkotlin/_18_object 小節(jié)

最后編輯于
?著作權歸作者所有,轉載或內(nèi)容合作請聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個濱河市禾嫉,隨后出現(xiàn)的幾起案子灾杰,更是在濱河造成了極大的恐慌,老刑警劉巖熙参,帶你破解...
    沈念sama閱讀 211,817評論 6 492
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件艳吠,死亡現(xiàn)場離奇詭異,居然都是意外死亡孽椰,警方通過查閱死者的電腦和手機讲竿,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,329評論 3 385
  • 文/潘曉璐 我一進店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來弄屡,“玉大人,你說我怎么就攤上這事鞋诗“蚪荩” “怎么了?”我有些...
    開封第一講書人閱讀 157,354評論 0 348
  • 文/不壞的土叔 我叫張陵削彬,是天一觀的道長全庸。 經(jīng)常有香客問我,道長融痛,這世上最難降的妖魔是什么壶笼? 我笑而不...
    開封第一講書人閱讀 56,498評論 1 284
  • 正文 為了忘掉前任,我火速辦了婚禮雁刷,結果婚禮上覆劈,老公的妹妹穿的比我還像新娘。我一直安慰自己沛励,他們只是感情好责语,可當我...
    茶點故事閱讀 65,600評論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著目派,像睡著了一般坤候。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上企蹭,一...
    開封第一講書人閱讀 49,829評論 1 290
  • 那天白筹,我揣著相機與錄音,去河邊找鬼谅摄。 笑死徒河,一個胖子當著我的面吹牛,可吹牛的內(nèi)容都是我干的送漠。 我是一名探鬼主播虚青,決...
    沈念sama閱讀 38,979評論 3 408
  • 文/蒼蘭香墨 我猛地睜開眼,長吁一口氣:“原來是場噩夢啊……” “哼螺男!你這毒婦竟也來了棒厘?” 一聲冷哼從身側響起纵穿,我...
    開封第一講書人閱讀 37,722評論 0 266
  • 序言:老撾萬榮一對情侶失蹤,失蹤者是張志新(化名)和其女友劉穎奢人,沒想到半個月后谓媒,有當?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,189評論 1 303
  • 正文 獨居荒郊野嶺守林人離奇死亡何乎,尸身上長有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點故事閱讀 36,519評論 2 327
  • 正文 我和宋清朗相戀三年句惯,在試婚紗的時候發(fā)現(xiàn)自己被綠了。 大學時的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片支救。...
    茶點故事閱讀 38,654評論 1 340
  • 序言:一個原本活蹦亂跳的男人離奇死亡抢野,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出各墨,到底是詐尸還是另有隱情指孤,我是刑警寧澤,帶...
    沈念sama閱讀 34,329評論 4 330
  • 正文 年R本政府宣布贬堵,位于F島的核電站恃轩,受9級特大地震影響,放射性物質發(fā)生泄漏黎做。R本人自食惡果不足惜叉跛,卻給世界環(huán)境...
    茶點故事閱讀 39,940評論 3 313
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望蒸殿。 院中可真熱鬧筷厘,春花似錦瞒瘸、人聲如沸籍胯。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,762評論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽楣铁。三九已至玖雁,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間盖腕,已是汗流浹背赫冬。 一陣腳步聲響...
    開封第一講書人閱讀 31,993評論 1 266
  • 我被黑心中介騙來泰國打工, 沒想到剛下飛機就差點兒被人妖公主榨干…… 1. 我叫王不留溃列,地道東北人劲厌。 一個月前我還...
    沈念sama閱讀 46,382評論 2 360
  • 正文 我出身青樓,卻偏偏與公主長得像听隐,于是被迫代替她去往敵國和親补鼻。 傳聞我的和親對象是個殘疾皇子,可洞房花燭夜當晚...
    茶點故事閱讀 43,543評論 2 349

推薦閱讀更多精彩內(nèi)容