scala之对象

来源:互联网 发布:苹果越狱会清除数据吗 编辑:程序博客网 时间:2024/06/05 23:05

单例对象

  Scala没有静态方法或静态字段,你可以用object这个语法结构来达到同样的目的。对象定义了某个类的单个实例,包含你想要的特性。如,

object Number {  private var num = 0;  def newUniqueNum() = {    num += 1    num  }  def main(args: Array[String]) {    println(Number.newUniqueNum()) //打印1  }}

注:Scala的单例对象和Java中的静态方法/字段调用方式一致。在Scala中,对象的构造器在该对象第一次被使用时调用,若一个对象从未被使用,那么其构造器也不会被执行。对象本质上可以拥有类的所有特性-它甚至可以扩展其它类或特质,但是你不能提供构造器参数。


Scala单例对象使用场景

  1.作为存放工具函数或常量的地方

  2.高效共享单个不可变实例

  3.需要单个实例来协调某个服务时(可参考单例模式)


伴生对象

  在Java或C++中,你通常会用到即有实例方法又有静态方法的类。在Scala中,你可以通过类和与类同名的“伴生”对象来达到同样的目的。如

class Num {  private val id = Num.newUniqueNum  private def test() = {}}object Num {  private var num = 0  new Num().test()  private def newUniqueNum = {num += 1; num}}
注:类和它的伴生对象可以相互访问私有特性;它们必须存在于同一个源文件中;类的伴生对象可以被访问,但并不在作用域中,Num类必须通过Num.newUniqueNum而不是直接用newUniqueNum来调用伴生对象的方法。

扩展类或特质的对象

  一个对象可以扩展类以及一个或多个特质,其结果是一个扩展了指定类以及特质的类的对象,同时拥有在对象中给出的所有特性。一个有用的场景是给出可被共享的缺省对象。举例在来说,考虑在程序中引入一个可撤销动作的类,默认情况下什么都不做,对于这个行为你只需要一个实例即可,可通过对象扩展类实现。如下,

//定义供扩展的抽象类abstract class UndoableAction(val description : String) {  def undo() : Unit  def redo() : Unit}//DoNthingAction扩展自UndoableAction,默认情况下什么都不做。object DoNothingAction extends UndoableAction("Do nothing") {  override  def undo() {}  override def redo() {}}

注:DoNothingAction对象可以被所有需要这个缺省行为的地方共用。


apply方法

  我们通常会定义使用对象的apply方法。当遇到如下形式的表达式时,apply方法就会被调用:

                           Object(参数1, ..., 参数N)

通常,这样一个apply方法返回的是伴生类的对象。举例来说,Array对象定义了apply方法,让我们可以用下面这样的表达式来创建数组:

                           Array("a","b","c")

为什么我们不使用构造器呢?对于嵌套表达式而言,省去new关键字会方便很多。如,Array(Array(1,7), Array(2,6))。

  我们来看一个示例:

class Account(val id: Int, initBalance: Double) {  private var balance = initBalance  def printTe() = println(balance)}object Account {  def apply(initBalance: Double) = {    new Account(1, initBalance)  }}object Test {  def main(args: Array[String]) {    val account = Account(2.0)    account.printTe  }}
注:输出结果为2.0。


应用程序对象

  每个Scala程序都必须从一个对象的main方法开始,这个方法的类型为Array[String] => Unit。如,

object Test {  def main(args: Array[String]) {    println("Hello, World!")  }}
注:输出结果为Hello, World!。

  除了每次都提供自己的main方法外,你也可以扩展App特质,然后将程序代码翻入构造器方法体内。如,

object Hello extends App {  println("Hello, World!")}
注:输出结果为Hello, World!。

   如果你需要命令行参数,则可以通过args属性得到,如

object Hello extends App {  if(args.length > 0){    println("Hello, " + args(0))  }  else{    println("Hello, World!")  }}
在类文件目录下执行如下命令

scalac Hello.scalascala -Dscala.time Hello Ming
注:输出结果为Hello, Ming。如果在你在调用该程序时设置了scala.time选项的话,程序退出时会输出消耗的时间。App特质扩展自另一个特质DelayedInit,编译器对该特质有特殊处理。所有带有该特质的类,其初始化方法都会被挪到delayedInit方法中。App特质的main方法捕获到命令行参数,调用delayedInit方法,并且还可以根据要求打印消耗的时间。

枚举

  和Java或C++不同,Scala并没有枚举类型。但是,标准库提供了一个Enumeration助手类,可以用于产出枚举类。例如,定义一个扩展Enumeration类的对象并以Value方法调用初始化枚举中的所有可选值。示例如下,

object Color extends Enumeration {  val Red, Yellow, Green = Value //等同于:val Red = Value; val Yellow = Value; val Green = Value;}

注:上述示例定义了三个字段:Red、Yellow、Green,然后用Value调用将它们初始化。每次调用Value方法都返回内部类的新实例,该内部类也叫做Value。或者你也可以向Value方法传入ID、名称或者两个参数都传。如果不指定,则ID在将前一个枚举值的基础上加一,从零开始。缺省字段名称为字段的名。定义完成后,你就可以用Color.Red、Color.Yellow、Color.Green来引用枚举值了。如果这些变得冗长繁琐,则可以通过import Color._语句直接引入枚举类,然后直接调用Red等字段即可。记住枚举的类型是Color.Value而不是Color,后者是握有这些值的对象。

  完整示例1:

object Color extends Enumeration {  val Red = Value(0, "Red")  val Yellow = Value("Yellow")  val Green = Value("Green")}object TestEnum {  def main(args: Array[String]): Unit = {    for(color <- Color.values) {      if(color.id == 2){        print(color.id + ": " + color)      }      else{        print(color.id + ": " + color + ",")      }    }  }}
注:输出结果为0: Red,1: Yellow,2: Green。
  完整示例2:

object Color extends Enumeration {  val Red = Value(0, "Red")  val Yellow = Value("Yellow")  val Green = Value("Green")}import Color._object TestEnum {  def main(args: Array[String]): Unit = {    for(color <- values) {      if(color.id == 2){        print(color.id + ": " + color + ".")      }      else{        print(color.id + ": " + color + ",")      }    }  }}
注:输出结果为0: Red,1: Yellow,2: Green。上述示例中,你可以直接使用Red、Yellow、Green。
  完整示例3:
object Color extends Enumeration {  type Color = Value //定义类型别名  val Red = Value(0, "Red")  val Yellow = Value("Yellow")  val Green = Value("Green")}import Color._object action {  def doWhat(color: Color) = {    if(color == Red) "stop"    else if(color == Yellow) "hurry up"    else "go"  }}object TestEnum {  def main(args: Array[String]) {    println(action.doWhat(Color.Green))  }}

注:输出结果为go。上述示例中使用type关键字定义类型别名,则该枚举的类型变成了Color.Color。

  完整示例4:

object Color extends Enumeration {  type Color = Value  val Red = Value(0, "Red")  val Yellow = Value("Yellow")  val Green = Value("Green")}object TestEnum {  def main(args: Array[String]) {    print(Color(0) + ":" + Color.withName("Yellow"))  }}
注:输出结果为Red:Yellow。其中,Color(0)将调用Enumeration.apply。
原创粉丝点击