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

最后欢迎大家留言评论,转发分享,点个关注哦!


分享到:


相關文章: