美文网首页
《快学Scala》——对象、包

《快学Scala》——对象、包

作者: 不做作就会屎星人 | 来源:发表于2017-07-04 20:21 被阅读51次

    单例对象

    Scala没有静态方法静态字段,可以用object来达到同样目的。

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

    对象本质上可以拥有类的所有特性,只有一个例外:不能提供构造器参数。

    伴生对象

    在Scala中,可以通过定义和类同名的(伴生)对象来提供其他语言(例如Java)中既有实例方法又有静态方法的类。类和它的伴生类可以互相访问私有特性,但必须定义在同一个源文件中。

    class Accounts {
        val id = Account.newUniqueNumber()
        private var blance = 0.0
        def deposit(amount: Double) {
          blance += amount
        }
        ...
    }
    object Accounts {  // 伴生对象
        private var lastNumber = 0
        def newUniqueNumber() = { lastNumber += 1; lastNumber }
    }
    

    注:object可以扩展类以及一个或多个特质,结果是一个扩展了指定类以及特质的类的对象。

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

    object(参数1,参数2,...,参数n)
    

    通常,这样一个apply方法返回的是伴生类的对象。示例如下:

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

    枚举

    Scala并没有枚举类型,但是可以通过标准类库的Enumeration助手类,产生枚举。定义一个扩展Enumeration类的对象并以Value方法调用初始化枚举中的所有可选值。

    object TrafficLightColor extends Enumeration {
        val Red = Value(0, "Stop")
        val Yellow = Value(10)  // 缺省名称为字段名
        val Green = Value("Go") // ID不指定时, 将在前一个枚举值基础上加一, 从零开始
        // 也可以简写为: val Red, Yellow, Green = Value
    }
    

    上例中,枚举的类型是TrafficLightColor .Value而不是TrafficLightColor。枚举值的ID可以通过id方法返回,名称可以通过toString方法返回。

    // values方法获得所有枚举值得集
    for (c <- TrafficLightColor.values) println(c.id + ": " + c)
    // 通过枚举的ID或名称来进行查找定位
    println(TrafficLightColor(2))
    println(TrafficLightColor.withName("Red"))
    

    同样的类名出现在不同的包中是不冲突的。在使用这样的类的时候可以使用完全限定的名称(包名.类名),也可以使用引入语句(import)。Scala的包和其他作用域一样地支持嵌套。通过下面形式的定义,可以访问上层作用域中的名称。

    package com {
        package horstmann {
            object Utils {
              def percentOf(value: Double, rate: Double) = value * rate /100
              ...
            }
            package impatient {
                class Employee {
                  ....
                  def giveRaise(rate: scala.Double) {
                    salary += Utils.percentOf(salary, rate)  // 因为Utils类定义在父包中,所有父包中的内容都是在作用域内的,因此没必要在前面加包名
                  }
                }
            }
        }
    }
    

    串联式包语句,限定了可见的成员。

    package com.horstmann.impatient {
        // com和com.horstmann的成员在这里不可见
        package people {
            class Person
            ...
        }
    }
    

    文件顶部标记法,可以在文件顶部使用package语句,不带花括号。这样做的话,表示文件中的所有代码均属于同一个包下。

    package com.horstmann.impatient 
     // com和com.horstmann的成员在这里不可见
    package people 
    class Person {
      ...
    }
    

    包对象

    可以将工具类或者常量添加到包对象中,用package object定义包对象:

    package com.horstmann.impatient
    
    package object people {
        val defaultName = "test"
    }
    
    package people {
        class Person {
            var name = defaultName // 从包对象拿到的常量
            ...
        }
    }
    

    注:defaultName不需要加限定词,因为它位于同一个包内。在其他地方,这个常量可以用com.horstmann.impatient.people.defaultName

    包可见性

    在Java中,没有被声明为public、private或protected的类成员在包含该类的包中可见。在Scala中,可以通过修饰符达到同样的效果。

    package com.horstmann.impatient.people
    class Person {
        // 在包impatient中可见
        private[impatient] def desc = "A person with name " + name
    }
    

    引入

    import java.awt.Color
    // 引入包下所有成员
    import java.awt._
    // 引入类或对象的所有成员
    import java.awt.Color._
    

    在Scala中,import语句可以出现在任何地方,并不局限在文件顶部。import语句的效果一直延伸到包含该语句的代码块的末尾。

    import java.awt.{Color, Font}  // 引入包中多个成员时,可以使用选取器(selector)
    import java.util.{HashMap => JavaHashMap}  // 还可以重命名选到的成员
    
    // 选取器HashMap => _将隐藏某个成员,这样HashMap无二义地指向scala.collection.mutable.HashMap
    import java.util.{HashMap => _, _}  
    import scala.collection.mutable._
    

    每个scala程序都隐式地以如下代码开始,这里的引入,允许覆盖之前的引入(例如scala.StringBuilder会覆盖java.lang.StringBuilder而不是与之冲突)。由于scala包默认被引入,对于那些以scala开头的包,可以省略scala。

    import java.lang._
    import scala._
    import Predef._
    

    相关文章

      网友评论

          本文标题:《快学Scala》——对象、包

          本文链接:https://www.haomeiwen.com/subject/owmxhxtx.html