共计 2020 个字符,预计需要花费 6 分钟才能阅读完成。
伴生对象和伴生类
在后面的文章中,可能也有人留神到 main 办法并没有像 java 的 static 关键字,而且运行 main 办法的类定义的是 object。object 定义的类和 class 定义的类名字还能够一样。
比方 class ScalaObject 和 object ScalaObject,咱们能够说 object ScalaObject 是 class ScalaObject 的伴生对象,class ScalaObject 是 object ScalaObject 的伴生类。伴生对象和伴生类能够互相拜访公有的属性和办法。
在 scala 中定义伴生对象的属性和办法:
object ScalaObject2 {
var str: String = "str"
def fun(): Unit = {println("fun")
}
}
编译后会看到有 ScalaObject2 和 ScalaObject2$ 两个 class 文件。
ScalaObject2 反编译如下,这里有 3 个静态方法,一个是咱们下面定义的 fun,另外一个就是 str 的 set 和 get 办法。ScalaObject2.str 就是调用 get 办法,ScalaObject2.str=”str2″ 就是调用 set 办法。
在 static 里能间接调用 ScalaObject2..MODULE$,所以咱们晓得 ScalaObject2..MODULE$ 也是动态的。
ScalaObject2$ 反编译如下,从这里能够看出,他实际上是一个单例对象。构造函数用 private 润饰,而后又用 this 指向 MODULE$,让 MODULE$ 对外提供办法。
在上面的例子中,str 是伴生类 ScalaObject 的公有属性,在伴生对象 ScalaObject 中,是能够间接拜访的,所以伴生对象和伴生类能够互相拜访公有的属性和办法。
class ScalaObject {private var str: String = "str"}
object ScalaObject {def main(args: Array[String]): Unit = {val scalaObject = new ScalaObject()
println(scalaObject.str)
}
}
单例
相似 java 的单例模式:
首先结构器默认 private 的,此时是不能间接通过结构器来创立这个对象,而后在伴生对象中,申明一个办法用于创立这个对象,因为伴生对象和伴生类能够相互调用公有办法,所以是能够通过结构器来创立这个对象。
object ScalaObject3 {
private val scalaObject3: ScalaObject3 = new ScalaObject3
def getInstance(): ScalaObject3 = {scalaObject3}
}
class ScalaObject3 private() {}
而后在 Test 中创立一个单例,间接通过 new 是不行的,所以通过伴生对象来获取。运行后,能够看到两个地址是一样的。
object Test {def main(args: Array[String]): Unit = {//new ScalaObject3()//erro
val scalaObject1 = ScalaObject3.getInstance()
val scalaObject2 = ScalaObject3.getInstance()
println(scalaObject1)
println(scalaObject2)
}
}
apply
咱们在伴生对象中定义 apply 办法,而后间接类目 + 参数(有可能无参),实际上调用的是伴生对象的 apply 办法。
比方在上面例子中,间接调用 ScalaObject4(“hello”) 实际上调用的是 ScalaObject4.apply 办法,所以 apply 是能够省略的。
object Test4 {def main(args: Array[String]): Unit = {ScalaObject4("hello")
ScalaObject4.apply("hello")
}
}
object ScalaObject4 {def apply(str: String): Unit = {println(str)
}
}
另外一个就是能够省略到 new 关键字。上面例子中,ScalaObject5 的结构器是公有的,所以间接 new 一个对象是不行的,ScalaObject5 是调用 apply 办法才返回的 ScalaObject5 实例。
比方 List(1,2,3),其实就是调用 apply 办法。
object Test5 {def main(args: Array[String]): Unit = {
val scalaObject = ScalaObject5
//val scalaObject1 = new ScalaObject5 erro
}
}
object ScalaObject5 {def apply(): ScalaObject5 = {new ScalaObject5}
}
class ScalaObject5 private{}