1.包:

包也可以像内部类那样嵌套。位于文件顶部的不带花括号的声明对整个文件都有效。如下代码:

package com.vip.scala.packages

package com{
  package hadoop{
    package cdn{
      //此类的包结构:com.vip.scala.packages.com.hadoop.cdn.Navigator
      class Navigator{        
      }
      //此包目录结构:com.vip.scala.packages.com.hadoop.cdn.test
      package test{    
        }      
    }
  }
}

相比于java,Scala的包定义相当随意。不只是在文件头,在代码的任意位置都可以定义嵌套包。


2.作用域

如下面程序,Calculators类位于父包内,所有父包中的内容都在作用域内,所以不需要引用scope.Calculators,直接使用Calculators即可。

package com{
  //scope包定义
  package scope{
       object Calculators {
         def calSalary(salary:Double,level:Int) ={salary + 10000*level}
       } 

      //human包定义
      package human{
        class Employee{
          var salary = 300000
          val level = 3
          def giveSalary() = { Calculators.calSalary(salary, level) }
        }
      }
  
   }
}

上边省略的写法(com.scope.Calculators 写成 Calculators)可能会有问题。假如,我们在human包里定了一个新类Manager,这个类调用了scala.collection.mutable.ArrayBuffer,这个是Scala默认引入的包,这时候如果不写scala;如果在外面其他地方(其他文件中补充定义com.scope包),在com.scope中也定义了一个collection包的话,就会发生冲突,编译器会使用com.scope.collection包内容,而不使用scala.collection包内容。如下代码:

package com{
  //scope包定义
  package scope{
       object Calculators {
         def calSalary(salary:Double,level:Int) ={salary + 10000*level}
       } 

      //human包定义
      package human{
        class Employee{
          var salary = 300000
          val level = 3
          def giveSalary() = { Calculators.calSalary(salary, level) }
        }
        
        //Manager类引用了,系统自带包scala.collection.mutable.ArrayBuffer
        class Manager{
          //报错:object mutable is not a member of package com.vip.scala.packages.com.scope.collection
          var employee_list = new collection.mutable.ArrayBuffer[Employee]
        }
      }
  
   }
}

package com{
  package scope{
    package collection{}
  }
}

为了规范,建议写完整的路径名。


3.串联式包语句:

包语句可以包含一个串(用点号分隔),这样的包语句限定了可见的成员,例如如果上边程序中的Manager类,我不使用下边的格式定义:

package com{

  package scope{

      package human{

          class Manager{ ... }

      }

  }

}

而是以package com.scope.human{ ... } 格式定义的化,就代表不可见com.scope包的内容,也就不可见com.scope.collection了,也就不会出现错误了。

package com.scope.human{
          class Manager{
          //由于限定了包com.scope的可见性,所以无法访问到包com.scope.collection了,所以不报错了。
          var employee_list = new collection.mutable.ArrayBuffer[Employee]
        }
}


另外在程序顶端,定了的包package com.vip.scala.packages,这里没加花括号,其等同于有效区域到文件末尾的带花括号的package定义。


4.包对象:

在java中,在一个包中只能定义类,不可以定义函数或者变量(方法或变量在包中的类中定义)。Scala对这个功能进行了扩展,使用包对象可以完成这个功能,在包中定义变量或者函数。

每个包都可以有包对象,需要在父包中定义,并且名称与子包一样

package com.vip.scala.packages

//在父包com.vip.scala.packages中定义包对象PackageTest,并且名称与子包PackageTest一致。
package object PackageTest{
  val package_variable = "This var can be used by everyone in the package!!!"
}

package PackageTest{
    class Gun {
      //从包对象中拿到常量
      var name = package_variable
      def getName() = {name}
    }
}


5.包可见性和import的使用:

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

package com.seeable.valrs
{
  class Road {
    private[seeable] def roadmap = "ChaoYang Road"
  }  
}

在com.seeable包内可见。


在java中,import语句只能写在文件顶部,而在Scala中可以写在任何位置。Scala中使用下划线替代java中的星号,另外scala更灵活。

import java.awt._  

这句话引入java.awt包中的所有成员。

improt java.awt.Color._

引入java.awt.Color类的所有成员。


为了防止不同包下的同名类的冲突,可以使用选取器只引入包中部分内容。

import java.awt.{Color,Font} 只引入java.awt包下的Color和Font类。

import java.util.{HashMap => _,_} :引入java.util包下除了HashMap的所有成员。


在Scala编译环境,在不写任何import语句时,默认引入下面三个包:

import java.lang._

import scala._

import Predef._