Scala 对象

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
原文地址:https://www.cnblogs.com/nowgood/p/Scalaobject.html