分享

Scala中的对象

happy22 发表于 2015-6-24 17:35:58 [显示全部楼层] 回帖奖励 阅读模式 关闭右栏 0 12467
本帖最后由 happy22 于 2015-6-24 17:37 编辑
问题导读:
1.Scala中有没有静态方法或静态字段,以及如何实现这种功能?
2.什么是伴生对象,它的特点是什么?
3.apply方法的特点是什么?



Scala中没有静态方法或静态字段,但可以使用object这个语法结构来实现相同的功能。对象与类在语法层面上很相似,除了不能提供构造器参数外,对象可以拥有类的所有特性。
Scala的object定义了单个实例,其可以用来存放工具函数或常量等:

[mw_shl_code=applescript,true]object Timer {
  var count = 0

  def currentCount(): Long = {
    count += 1
    count
  }
}
[/mw_shl_code]

使用object中的常量或方法,通过object名称直接调用,对象构造器在对象第一次被使用时调用(如果某对象一直未被使用,那么其构造器也不会被调用)。

[mw_shl_code=applescript,true]scala> Timer.currentCount()
res52: Long = 1

scala> Timer.currentCount
res53: Long = 2

scala> Timer.count
res54: Int = 2
[/mw_shl_code]

object的构造器不接受参数传递。

伴生对象

对象如果与某个类同名,那么它就是一个伴生对象。类和它的伴生对象必须在同一个源文件中,可以将在Java类中定义的静态常量、方法等放置到Scala的类的伴生对象中。

类可以访问伴生对象私有属性,但是必须通过伴生对象.属性名 或 伴生对象.方法 调用,伴生对象也可以访问类的私有属性。
伴生对象是类的一个特殊实例。

[mw_shl_code=applescript,true]

class Counter{
    def getTotalCounter()= Counter.getCount
}

object Counter{
    private var cnt = 0
    private def getCount()= cnt
}
[/mw_shl_code]对象可以继承类,以及一个或多个特质,其结果是一个继承了指定类以及特质的类的对象,同时拥有在对象定义中给出的所有特性。

[mw_shl_code=applescript,true]abstract class Person(var name:String, var age:Int){
    def info():Unit
}

object XiaoMing extends Person("XiaoMing", 5){
    def info(){
        println(" name is "+name+", age is "+age)
    }
}
[/mw_shl_code]


Java程序通常从一个public类的main方法开始。而在Scala中,程序从对象的main方法开始,方法的类型是 Array[String] => Unit。

[mw_shl_code=applescript,true]object Hello {
  def main(args: Array[String]) {
    println("Hello, world!")
  }
}
[/mw_shl_code]


除此之外,还可以扩展App特质,然后将程序代码放在构造器内即可,命令行参数从args属性获取。

[mw_shl_code=applescript,true]object Hello extends App {
  if (args.length > 0)
    println("Hello, " + args(0))
  else
    println("Hello, world!")
}
[/mw_shl_code]


apply 方法

apply方法是对象的一类特有方法,一般可用于创建伴生类。apply方法可以用简洁的方式调用,形如Object(args..), 当然,你也可以跟其他方法一样调用,Object.apply(args...),这两种写法的结果是一样的。
现在,当你看到List(1,2,3)这样的语句就不会感到奇怪了,这只是List.apply(1,2,3)的简写而已。
使用apply方法的好处是,在创建对象时,可以省去使用new关键字
当类或对象有一个主要用途的时候,apply方法为你提供了一个很好的语法糖。

[mw_shl_code=applescript,true]scala> class Foo {}
defined class Foo

scala> object FooMaker {
     |   def apply() = new Foo
     | }
defined module FooMaker

scala> val newFoo = FooMaker() //没有new
newFoo: Foo = Foo@5b83f762
[/mw_shl_code]


或者:

[mw_shl_code=applescript,true]scala> class Bar {
     |   def apply() = 0
     | }
defined class Bar

scala> val bar = new Bar
bar: Bar = Bar@47711479

scala> bar()
res8: Int = 0
[/mw_shl_code]


枚举

在Scala中并没有枚举类型,但在标准类库中提供了Enumeration类来获得枚举。扩展Enumeration类后,调用Value方法来初始化枚举中的可能值。

[mw_shl_code=applescript,true]object TrafficLightColor extends Enumeration {
  val Red, Yellow, Green = Value
}
[/mw_shl_code]


上述实例中代码可以改为下面这样,区别是:Value方法每次返回内部类Value的新实例。

[mw_shl_code=applescript,true]val Red = Value
val Yellow = Value
val Green = Value
[/mw_shl_code]


用Value方法初始化枚举类变量时,Value方法会返回内部类的新实例,且该内部类也叫Value。另外,在调用Value方法时,也可传入ID、名称两参数。如果未指定ID,默认从零开始,后面参数的ID是前一参数ID值加1。如果未指定名称,默认与属性字段同名。

[mw_shl_code=applescript,true]object TrafficLight extends Enumeration{
     val Red = Value(1, "Stop")
     val Yellow = Value("Wait")    //可以单独传名称
     val Green = Value(4) //可以单独传ID
}
[/mw_shl_code]


上例中,Yellow属性就仅定义了名称,Green仅定义ID。
参数在不指定名称时,默认参数的Value为字段名。枚举类型的值是 对象名.Value ,如上例中的枚举类型是 TrafficLight.Value。

[mw_shl_code=applescript,true]TrafficLight.Green
//TrafficLight.Value = Green
[/mw_shl_code]


通过id方法获取枚举类型值的ID:

[mw_shl_code=applescript,true]TrafficLight.Yellow.id
//Int = 2
[/mw_shl_code]


通过values方法获取所有枚举值的集合:

[mw_shl_code=applescript,true]TrafficLight.values
//TrafficLight.ValueSet = TrafficLight.ValueSet(Stop, Wait, Green)
[/mw_shl_code]


通过ID来获取对应的枚举对象:
[mw_shl_code=applescript,true]TrafficLight(1)
//TrafficLight.Value = Stop
[/mw_shl_code]

没找到任何评论,期待你打破沉寂

您需要登录后才可以回帖 登录 | 立即注册

本版积分规则

关闭

推荐上一条 /2 下一条