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
最后欢迎大家留言评论,转发分享,点个关注哦!
閱讀更多 Java高級架構技術 的文章