快学Scala第7章----包和引入

来源:互联网 发布:单源最短路径算法spfa 编辑:程序博客网 时间:2024/06/10 22:04

快学Scala第7章—–包和引入

本章要点

  • 包也可以像内部类那样嵌套
  • 包路径不是绝对路径
  • 包声明链x.y.z并不自动将中间包x和x.y变成可见
  • 位于文件顶部不带花括号的包声明在整个文件范围内有效
  • 包对象可以持有函数好变量
  • 引入语句可以引入包、类和对象
  • 引入语句可以出现在任何位置
  • 引入语句可以重命名和隐藏特定成员
  • java.lang、scala和Predef总是被引入

要增加条目到包中:

package com {    package horstmann {        package impatient {            class Employee            ...        }    }}

这样你就可以在任意的地方以com.horstman.impatient.Employee访问到了Employee类。 与对象或这类的定义不同,同一个包可以定义在多个文件中。


作用域规则

Scala的包和其他作用域一样的支持嵌套,你可以访问上层作用域中的名称:

package com {    package horstman {        object Utils {            def percentOf(value: Double, rate: Double) = value * rate / 100            ...        }    }    package impatient {        class Employee {            ...            def giveRise(rate: Double) {                salary += Utils.percentOf(salary, rate)            }        }    }}

在不同的文件中定义一个包,可能会出现一个问题:两个文件在定义包时覆盖了正确的包;

// 在一个文件中package com {    package horstmann {        package impatient {            class Manager {                val subordinates = new collection.mutable.ArrayBuffer[Employee]                ...            }        }    }}// 在另一个文件中package com {    package horstmann {        package collection {            ...        }    }}

由于Scala允许使用相对路径的包名,自定义了collection之后,在com的作用域中就会使用自定义的包,就会在自定义的包中找ArrayBuffer,这样是错误的。解决方法之一是使用绝对包名,以root开始:

val subordinates = new _root_.scala.collection.mutable.ArrayBuffer[Employee]

另一种做法是使用串联式包语句,例如:

package com.horstmann.impatient {    // com和horstmann的成员在这里不可见    class Manager {        val subordinates = new collection.mutable.ArrayBuffer[Employee]        ...    }}

现在com.horstmann.collection包不再能够以collection 访问到了。


文件顶部标记法

在文件的顶部使用package语句,不带花括号:

package com.horstmann.impatientpackage peopleclass Person...// 这等同于package com.horstmann.impatient {    package people {        class Person        ...        // 直到文件末尾    }}

因此,你可以直接引用com.horstmann.impatient包中的内容。


包对象

包可以包含类、对象和特质,但不能包含函数或变量的定义。每个包都可以有一个包对象,你需要在父包中定义它,且名称与子包一样:

package com.horstmann.impatientpackage object people {    val defaultNmae = "John Q. Public"}package people {    class Person {        val name = defaultName  // 从包中拿到的常量    }    ...}

在这里,使用defaultName时不需要加上限定词,因为它位于同一个包内。在其他地方,这个常量可以用com.horstmann.impatient.people.defaultNmae访问到。
在幕后,包对象被编译成带有静态方法和字段的JVM类,名为package.class,位于相应的包下。


包可见性

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

package com.horstmann.impatient.peopleclass Person {    private[people] def description = "A person whith name " + name  // people包中可见    // 扩展至上层包可见    private[impatient] def description = "A person whith name " + name}

引入

引入语句可以让你使用更短的名称:

import java.awt.Color// 引入某个包的全部成员import java.awt._    // 这与Java中的通配符'*'一样// 你也可以引入类或对象的所有成员import java.awt.Color._val c1 = RED    // Color.REDval c2 = decode("#ff0000") // Color.decode

任何地方都可以声明引用

class Manager {    import scala.collection.mutable._    val subordinates = new ArrayBuffer[Employee]    ...}

重命名和隐藏方法

在Java和Scala中都有HashMap,用过两个都被引用了则会导致冲突。解决办法就是使用选取器,将某一个HashMap重命名或者干脆直接隐藏掉(前提是你不会使用到它)。

// 选取器import java.awt.{Color, Font}// 重命名某个成员import java.util.{HashMap => JavaHashMap}import scala.collection.mutable._// 隐藏某个成员import java.util.{HashMap => _, _}import scala.collection.mutable._

隐式导入

每个Scala程序都隐式的以如下代码开始

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

scala这和引入会覆盖java.lang包中冲突的成员。

0 0
原创粉丝点击