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

快学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.impatient
package people

class Person
...


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

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


包对象

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

package com.horstmann.impatient

package 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.people

class 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.RED
val 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包中冲突的成员。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值