1. 单例对象
对于任何你在Java中会使用单例对象的地方, 在scala中都可以使用对象来实现;
scala字段没有静态方法或者静态字段, 可以使用object语法结构达到同样的效果,对象(object)定义了某个类的单个实例;
对象构造器在对象第一次被使用时调用, 如果一个对象从来没有被使用过, 其构造器也不会被执行;
对象从本质本质上可以拥有类的所有特质, 只有一个例外, 你不能提供构造器参数
scala中对象的常见用法是:
- 作为存放工具函数或常量的地方
- 高效的共享单个不可变实例的地方
- 需要某个单例来协调某个服务时(参考单例模式)
2. 伴生对象(Companion Object)
在Java中你通常会用到既有实例方法又有静态方法的类, 在Scala中可以通过与类同名
的伴生对象达到同样目的.
类和她的伴生对象必须存在同一个源文件中(.scala), 可以相互访问私有属性, 类可以访问其伴生对象, 不过并不是因为在一个作用域中, 比如说 类HappyObject通过HappyObject.newUniqueName 而不是newUniqueName直接访问伴生对象的方法
class HappyObject {
val id = HappyObject.newUniqueName()
private var balance = 0.0
def deposit(amount: Double): Unit = {
balance += amount
}
}
// 伴生对象
object HappyObject {
private var lastNumber = 0
def newUniqueName() {
lastNumber += 1
lastNumber
}
}
3. apply方法
当遇到下面的情况时, apply方法就会被调用,
Object(参数1, 参数2, ...)
通常这样返回的是类的伴生对象
比如说Array对象定义了apply方法, 让我们可以通过下面的方法创建数组
Array("happy" , "goodday")
这里你可能问为什么不用构造器, 看到下面的嵌套表达式, 就可以看到省去new关键字会方便很多
Array(Array("happy", "smile") , Array("goodday", "shinning"))
△: Array(10) VS new Array(10)
Array(10) 调用的是伴生对象的apply方法, 输出一个单个元素的Array[Int];
new Array(10) 调用的是构造器this(100), 输出包含10个null元素的Array[Nothing]一般在apply方法中调用伴生类的构造器
4. 应用程序对象
每个scala程序都必须从一个对象的main方法
开始
这个方法的类型是 Array[String] => Unit
object Happy {
def main(args: Array[String]) {
print("hello world")
}
}
除了每次提供自己的main方法之外, 也可以继承App特质, 然后将程序代码写入构造方法体内;如果你在调用应用程序时设置scala.time选项的话, 控制台会显示程序执行时间; 如果需要命令行参数, 可以通过args属性得到.
object HappyApp extends App {
if(args.length > 0) println("happy" + args(0))
else println("happy ending")
}
scalac HappyApp.scala
scala -Dscala.time HappyApp start
5. 枚举
Scala对象没有枚举类型, 不过标准类库有一个scala.Enumeration助手类, 用于产生枚举
枚举对象的枚举值类型是一个内部类对象, 包含两个属性id
和名称
,这两个属性都可以设置,你也可以不设置或者设置1个
- 设置id: 如果不指定, id在前一个id的基础上加1, 从零开始, 指定id时确保id之前没有被用过,不能重复;
- 设置名称: 不设置名称的话, 默认名称是字段名
5.1 使用方法
定义一个继承Enumeration类的对象(比如叫Enum),并以Value方法调用初始化枚举中的所有可选值, 每次调用Value方法都会返回内部类(也叫Value)的新对象, 所以枚举值的类型是Enum.Value,而不是Enum
常用方法说明:
枚举值 | 说明 |
---|---|
Enum.green | 获取枚举值 |
Enum.green.id | 获取枚举值ID |
Enum.green.toString | 获取枚举值名称 |
Enum.values.values | 返回所有的枚举值的集合 |
Enum(2) | 通过 id 获取枚举值(调用Enumeration.apply) |
Enum.withName("green") | 通过名称获取枚举值 |
object Enum extends Enumeration {
val red, yellow, green = Value
val blue = Value(10, "hi, my color is blue")
def main(args: Array[String]): Unit = {
println(Enum.values)
println(Enum.green.toString)
println(Enum.green.id)
println(Enum(10))
println(Enum.withName("hi, my color is blue"))
println(Enum.green.getClass.getName)
}
/*output:
Enum.ValueSet(red, yellow, green, hi, my color is blue)
green
2
hi, my color is blue
hi, my color is blue
scala.Enumeration$Val
*/
}
5.2 类型别名
通过Enum.green的方式引用枚举值, 如果枚举对象的名字太长的话, 就会变得冗长, 可以通过下面方式引用枚举值
import Enum._
枚举值的类型是Enum.Value, 而不是Enum(Enum是握有这些值的对象), 所以有人推荐增加一个类型别名, 但是仅当会用import
语句时这样做才有意义
object Enum extends Enumeration {
type Enum = Value
val red, yellow, green = Value
val blue = Value(10, "hi, my color is blue")
现在Enum.Enum
也可以表示枚举值的类型
import chap04.Enum._
object ImportEnum {
def main(args: Array[String]): Unit = {
val stop: Enum = blue
println(blue)
}
}
//output: hi, my color is blue