Scala學習筆記系列:面向對象?那就先聊聊“對象”

Scala學習筆記系列:面向對象?那就先聊聊“對象”

Scala中有個特殊關鍵字object,通過聲明object類型,可以實現單例模式。在object類型內部,可以定義靜態屬性或方法,但第一次調用object實例中的方法時,會自動執行其構造器中的邏輯(即未定義在方法中的代碼,統一歸為構造器中的代碼)。但object類型不能定義構造器來接受入參。object類型對象的適用場景,一種是上面說的用於實現單例模式,另一種則是作為靜態工具類使用。先來看一個簡單的示例:

object HttpClient {
//初始化HttpClient
private var isproxy = false
println("HttpClient Initialized.")
isproxy = true
// 定義handler方法執行業務邏輯
def handlerRequest(url:String): String = {
printf("{url:%s, isproxy:%s}", url, isproxy)
return "HttpResponse"
}
}
HttpClient.handlerRequest("http://github.com")
HttpClient.handlerRequest("http://apache.org")

分析返回內容,可以發現初始化語句僅打印了一次:
defined object HttpClient
HttpClient Initialized.
{url:http://github.com, isproxy:true}
{url:http://apache.org, isproxy:true}

伴生對象

假設聲明一個class類,與此同時又聲明一個與之同名的object類型,那麼就將這個object類型稱為class類的伴生對象,而class則是object的伴生類。在Scala中伴生類和伴生對象緊密關聯,表現形式之一是兩者必須存在於同一個.scala文件中。此外,另一個特點是可以互相訪問通過private修飾的屬性。

object HttpClient { // 伴生對象
private var isproxy = false
println("HttpClient Initialized.")
isproxy = true

def handlerRequest(url:String): String = {
// 執行業務邏輯
printf("{url:%s, isproxy:%s}", url, isproxy)
return "HttpResponse"
}
}

class HttpClient { // 伴生類
def disableProxy: Unit = {
HttpClient.isproxy = false
printf("DisableProxy, isproxy:%s", HttpClient.isproxy)
}
}
HttpClient.handlerRequest("http://github.com")
// 創建HttpClient Class實例並調用disableProxy方法
var hc = new HttpClient
hc.disableProxy
HttpClient.handlerRequest("http://scala.org")

執行代碼後返回如下,可以發現調用class中的disableProxy方法後,可以將object中私有的isproxy屬性置為false:
HttpClient Initialized.
{url:http://github.com, isproxy:true}
DisableProxy, isproxy:false
{url:http://scala.org,isproxy:false}

object繼承抽象類

object類型與class非常類似,也可以繼承抽象類,並覆蓋抽象類中的方法。示例如下:

abstract class Action(var config: String) { // 定義抽象類
def execute(commond: String): Unit
}

object SubmitAction extends Action("apollo") { // 定義object類型繼承該抽象類
override def execute(command: String) = {
printf("config:%s, command:%s", config, command)
}
}
執行object中覆蓋的方法:
SubmitAction.execute("upload")// 返回config:apollo, command:upload

apply方法

Scala面向對象編程中,還有一個非常奇特的方法,稱為apply方法。一般在伴生對象中實現apply方法,用於對伴生類進行初始化。由於創建伴生類的實例時,通常採取Class()的方式(而非new Class形式)隱式地調用伴生對象中的apply方法。比如,Array類伴生對象的apply方法提供了接收變長參數並創建對象的功能:

val array = Array(1, 2, 3, 5, 8)

此外,還可以自定義伴生類和伴生對象:
class MyArray(var element: String)
object MyArray {
def apply(element: String) = {
printf("call apply to initialize class")
new MyArray(element)
}
}
// 通過MyArray形式實例化,默認會隱式調用apply方法
var array = MyArray("string") //返回call apply to initialize class

Scala中如果要通過命令行形式執行代碼,可以創建.scala文件,通過scalac進行編譯,然後使用scala命令執行。與JAVA非常相似。

scalac HttpClient.scala
scala -Dscala.time HttpClient

用object來實現枚舉Enumeration

由於Scala中沒有類似JAVA的枚舉類型,因此如果有類似需求,可以通過object實現。比如創建object類型來繼承Enumeration類,並且調用Value方法來初始化枚舉值:

object Status extends Enumeration {
val RUNNABLE, RUNNING, STOP, WAIT = Value
}

可以通過Value定義枚舉值的ID和NAME並通過ID和toString獲取;還可以通過ID和NAME來查找枚舉值:

object Status extends Enumeration {
val RUNNABLE = Value(1, "RUNNABLE")
val RUNNING = Value(2, "RUNNING")
val STOP = Value(3, "STOP")
val WAIT = Value(4, "WAIT")
}
println(Status(1))
println(Status.withName("STOP"))
// 使用枚舉object.values可以遍歷枚舉值
for (element // 返回RUNNABLE、RUNNING、STOP、WAIT

最後歡迎大家留言評論,轉發分享,點個關注哦!


分享到:


相關文章: