scala之旅-核心語言特性【單例物件】(十五)
object 是一個類有且唯一的例項。當物件被引用時,它是懶模式建立的,就像 lazy val一樣。
作為一個頂級的值,物件是單例的。
作為一個封閉類的成員或者區域性值時,它的行為更像是一個lazy val。
定義一個單例的物件
物件是一個值。定義一個物件看起來像定義一個類,但是是用關鍵字 object:
object Box
下面是一個關於物件的例子,這個物件有一個方法:
package logging object Logger { def info(message: String): Unit = println(s"INFO: $message") }
這個info 方法可以被程式的任何地方匯入。像這樣建立一個實用方法是對單例物件的普遍使用方式。
讓我們看看如何在其他包中使用info方法:
import logging.Logger.info class Project(name: String, daysToComplete: Int) class Test { val project1 = new Project("TPS Reports", 1) val project2 = new Project("Website redesign", 5) info("Created projects") // Prints "INFO: Created projects" }
通過import語句 import logging.Logger.info,info方法就可以被訪問。
import 需要一個全路徑,物件也是全路徑匯入。
注意:如果一個物件不是頂級的,但是是內嵌在其他類或者物件裡面的,那麼這個物件的需要用 全路徑+依賴的方式,與類其他成員訪問方式一樣。這意味著給定兩種飲料類,類 Milk和類 OrangeJuice, 一個類成員 object NutritionInfo 依賴於封閉的例項,無論是 milk 還是 orangeJuice,milk.NutritionInfo 和oj.NutritionInfo 都是不一樣的。
物件的比較
與類同名的物件稱之為伴生物件。相反,這個類稱之為伴生類。伴生類或物件可以訪問與其伴生的內部私有成員。將伴生物件用於伴生類例項中沒有指明的方法和值。
import scala.math._ case class Circle(radius: Double) { import Circle._ def area: Double = calculateArea(radius) } object Circle { private def calculateArea(radius: Double): Double = Pi * pow(radius, 2.0) } val circle1 = Circle(5.0) circle1.area
這裡的類 Circle有一個在例項指定的area成員,單例物件Circle有一個 calculateArea方法,這個方法每個例項都可以訪問。
伴生物件當然也可以包含工廠方法:
class Email(val username: String, val domainName: String) object Email { def fromString(emailString: String): Option[Email] = { emailString.split('@') match { case Array(a, b) => Some(new Email(a, b)) case _ => None } } } val scalaCenterEmail = Email.fromString("[email protected]") scalaCenterEmail match { case Some(email) => println( s"""Registered an email |Username: ${email.username} |Domain name: ${email.domainName} """.stripMargin) case None => println("Error: could not parse email") }
這個物件 Email 包含一個工廠 fromString 用來從一個字串中建立一個Email。 以防解析錯誤,我們用一個 Option[Email] 返回。
注:如果一個類或物件有伴生,那麼它們必須在一個檔案裡面定義。要在REPL中定義伴生,請在同一行上定義它們或進入:paste
模式 【注:這句話我沒看懂~】
Java開發者注意
java的static 成員被建模在scala的伴生物件的普通成員。
當從java程式碼中使用伴生物件時,伴生物件成員將會在伴生類裡面用一個static進行定義。這叫做靜態轉化,這個一般出現在即使你沒有定義伴生類的時候。