Scala学习六——对象

一.本章要点

  • 用对象作为但例或存放工具的方法
  • 类可以拥有一个同名的伴生对象
  • 对象可以扩展类或特质
  • 对象的apply方法通常用来构造伴生类的新实例
  • 如果不想显示定义main方法,可以扩展App特质的对象
  • 你可以通过扩展Enumeration对象来实现枚举

二.单例对象

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

  例:直接调用Accounts.newUniqueNumber()就可以创建一个新的唯一帐号,对象的构造器在该对象第一次被使用时调用,如果从未调用,则不会执行构造器。对象本质可以拥有类的所有特性,但是不能提供构造器参数。

object Accounts{
private var lastNumber=0
def newUniqueNumber()={lastNumber+=1;lastNUmber}

}

  

 

 

三.伴生对象

  在Java/C++中,通常使用到既有实例方法又有静态方法的类,在Scala中就可以通过类和类同名的”伴生“对象来实现,例:

 

class Account{
val id=Account.newUniqueNumber()
private var balance=0.0
def deposit(account:Double){

balance+=amount
}
}
object Account{
//伴生对象
private var lastNumber=0
private def newUniqueNumber()={lastNumber+=1;lastNumber}

}

 

  注:类和它的伴生对象可以相互访问私有属性,但是需要存在于同一个源文件中;

    

四.扩展类或特质的对象

  一个object可以扩展类以及一个或多个特质,其结果是一个扩展了指定类以及特质的类的对象,同时拥有在对象中给定的所有特性。

五.apply方法

  通常会定义和使用apply方法,当遇到Object(参数1,...,参数N)时,apply方法会被调用(通常apply方法返回的是一个伴生类的对象),如Array对象定义了apply方法,Array(Array(1,7),Array(2,9))而不用构造器,可以更加方便,省去new。

  例:

class Account private(val id:Int,initialBalance:Double){
private var balance=initialBalance
...
}
object Account{
//伴生对象
def apply(initialBalance:Double)={

new Account(newUniqueNumber(),initiaBalance)

}


}

 

六.应用程序对象

  • 每个Scala程序都必须从一个对象的main方法开始,这个方法类型为Array[String]=>Unit;
object Hello{
def main(args:Array[String]){
println("Hello")

}

}

 

  • 当然也可以扩展App特质,将程序代码放入构造器
object Hello extends App{
println("Hello")
}

 

  • 如果需要命令参数,则可以通过args属性(应用设置scala.time[-Dscala.time]时程序退出会显示逝去的时间)
object Hello extends App{
if(args.length>0){
println("Hello,"+args(0))
else{
println("Hello")
}
}

}

 

  注:App特质扩展自另一个特质DelayedInit,编译器对该特质有特殊的处理。所有带该特质的类,其初始化方法都会被挪到delayedInit方法中(查看API可知Scala2.13.1已经弃除)App特质的main方法捕获到命令参数,调用delayedInit方法,并且可以根据要求打印逝去的时间。

七.枚举

  和Java或C++不同,Scala并没有枚举类型,不过,标准库提供了一个Enumeration助手类,可以用于产出枚举。

  

object TrafficLightColor extends Enumeration{
val Red,Yellow,Green=Value
}

 

  每次调用Value方法都返回内部类的新实例,该内部类也叫Value。

  也可以向Value传入ID,名称,或两个参数都传(如果不指定,则ID就会将前一个枚举基础上加一,从零开始,缺省名称为字段名)。

  注:通过TrafficLightColor.Red来引用枚举值(也可以直接import TrafficLightColor._直接应用),枚举的类型为TrafficLightColor.Value而不是TrafficLightColor(拥有这些值的对象);

     

 

 

     枚举值的ID通过id方法返回,名称通过toString方法返回。

     输出所有的枚举值:

 for(c <- TrafficLightColor.values  println(c.id+":"+c))

 

     通过ID或名称定位:

TrafficLightColor(0) //调用Enumeration.apply
TrafficLightColor.withName("Red")

 

八.练习

 

 

   1.

 

object Conversations {
  private val i2c: Double = 30.48
  private val g2l: Double = 3.785411784
  private val m2k: Double = 1.609344

  def inchesToCentimeters(inc: Double): Double = {
    inc * i2c
  }

  def gallonsToLiters(gal: Double): Double = {
    gal * g2l
  }

  def milesTokilometers(mil: Double): Double = {
    mil * m2k
  }

  def main(args: Array[String]): Unit = {
    println(inchesToCentimeters(10))
    println(gallonsToLiters(10))
    println(milesTokilometers(10))
  }
}

 

   2.

abstract class UnitConversion {
  def Converse(comn: Double): Double


}

object InchesToCentimeters extends UnitConversion {
  private val i2c: Double = 30.48

  override def Converse(comn: Double) = {
    i2c * comn
  }
}

object GallonsToLiters extends UnitConversion {
  private val g2l: Double = 3.785411784

  override def Converse(comn: Double): Double = {
    g2l * comn
  }
}

object MilesTokilometers extends UnitConversion {
  private val m2k: Double = 1.609344

  override def Converse(comn: Double): Double = {
    m2k * comn
  }
}

object Test {
  def main(args: Array[String]): Unit = {
    println(InchesToCentimeters.Converse(10))
    println(GallonsToLiters.Converse(10))
    println(MilesTokilometers.Converse(10))
  }

}

   3.

 

   4.

   5.

   6.

   7.

   8.

posted @ 2019-11-28 15:35  biu嘟  阅读(188)  评论(0编辑  收藏  举报