essential scala: 伴生对象
有时候我们想创建属于类的方法,在java中使用static关键字. 在scala中使用单例对象实现. class中的方法可以看作是static的,对象中的方法则可以看作是对象所独有的方法.
一种常见应用就是实现多个构造函数. 虽然scala在语法上完全可以给一个class添加多个构造函数,但是scala程序员比较倾向于写一个同名单例对象,在这个单例中实现apply方法. 往往把这个同名对象叫做这个class的伴生对象(companion object).
class Timestamp(val seconds: Long)
object Timestamp {
def apply(hours: Int, minutes: Int, seconds: Int): Timestamp =
new Timestamp(hours*60*60 + minutes*60 + seconds)
}
Timestamp(1, 1, 1).seconds
// res: Long = 3661
在scala终端中定义伴生对象
键入 :paste
进入粘贴模式. 因为伴生对象必须和其对应的class同时编译,意味着他们必须被定义在一个文件中,在交互式终端中要使用:paste
. 使用:help
获取更多帮助.
scala> :paste
// Entering paste mode (ctrl-D to finish)
重点说明的一点是,伴生对象并不是一个类的实例,而是一个拥有自己类型的单例对象.
Timestamp // note that the type is `Timestamp.type`, not `Timestamp`
// res: Timestamp.type = Timestamp$@602b24e6
语法
在同一个文件中,同名.
class Name {
...
}
object Name {
...
}
总结
伴生对象与对应的类紧密关联,但是不必创建任何类的实例,常用于额外的构造函数.
伴生对象替代了java的static方法,同样的功能同时更加灵活.
伴生对象和类同名,不会产生命名冲突是因为scala的两个命名空间,值空间和类型空间,相互独立.
伴生对象和对应的类必须定义在同一源文件中,当在终端中定义时,使用 :paste
模式.
练习
写一个类Person的伴生对象,实现使用全名来初始化Person
Person类的定义如下
class Person(val firstname:String, val lastname:String) {
def name = firstname + " " + lastname
}
val
关键字将参数同时定义为类的属性值.
参考解答
object Person {
def apply(fullname:String) = {
val parts = fullname.split(" ")
new Person(parts(0), parts(1))
}
// another constructor without parameters
def apply() = new Person("yourfirstname","yourlastname")
}
终端中验证
scala> val p = Person("hell ooo")
p: Person = Person@11ce2e22
scala> p.firstname
res13: String = hell
scala> p.lastname
res14: String = ooo