scala学习笔记(九):包、包对象以及可见域

1、Scala的包Java中的包的目的是相同的:管理大型程序中的名称,与对象或类的定义不同,同一个包可以定义在多个文件当中

 

a.scala
package a{
  package b{
    package c{
      class A{
      }
    }
  }
}

b.scala
package a{
  package b{
    package c{
      class B{
      }
    }
  }
}

 2、包嵌套、包对象

object PackageB {
  def main(args: Array[String]): Unit = {
    new A()
    val b = new B("jack")
    b.say //输出: 2016-12-23:Hello!jack
    new D()
    new W()
  }
}

/**
  * 1、同一个包可以定义在多个文件当中
  * 2、源文件的目录和包之间并没有强制的关联关系。你不需要将PackageB.scala和PackageA.scala放在com/aralbox/p目录当中
  *    换个角度讲,你也可以在同一个文件当中为多个包贡献内容,而java来说是强制源文件的目录和包一致
  * 3、同时在同意个源文件中可以定义多个包
  */
package a{
  import java.text.SimpleDateFormat
  import java.util.Date

  //a.b包下的包对象
  package object b{
    def nowTime:String = {
      val fomart = new SimpleDateFormat("yyyy-MM-dd HH:mi:ss")
      fomart.format(new Date)
    }
  }

  package b{

    object Utils {
      //包嵌套 包下面的子包都能直接访问 不需要写全名
      def now:String = {
        val fomart = new SimpleDateFormat("yyyy-MM-dd")
        fomart.format(new Date)
      }
    }

    /**
      * 包对象
      * 1、包可以包含类、对象和特质,但不能包含函数或变量的定义。很不幸,这是Java虚拟机的局限
      * 2、把工具函数或常量添加到包而不是某个Utils对象,这是更加合理的做法
      * 3、包对象的出现正是为了解决这个局限。每个包都可以有一个包对象。你需要在父包中定义它,且名称与子包一样
      * 4、包对象被编译成带有静态方法和字段的JVM类,名为package.class,位于相应的包下a.b
      * 5、在JVM中,你可以使用package作为类名。对源文件使用相同的命名规则是好习惯,可以把包对象放到文件a/b/package.scala。
      *    这样一来,任何人想要对包增加函数或变量的话,都可以以很容易地找到对应的包对象
      */
    package object c{
      def now:String = {
        val fomart = new SimpleDateFormat("yyyy-MM-dd")
        fomart.format(new Date)
      }
    }

    package c{
      //类也可以申明类的可见范围 那么在a.b下面的类都可以直接使用B类 因为是private 那么不是此包下面的是不能访问的
      protected [p] class B(name:String){
        /**
          * 在Java中,没有被声明为public、private或protected的类成员在包含该类的包中可见。在Scala中,你可以通过修饰符达到同样的效果
          * 这样age 只能在a.b.c包中可见
          */
        private[c] var age:Int = 20
        //你可以将可见度延展到上层包a.b
        private[b] var height:Int = 170
        //使用父包的对象的方法
        def say = println(Utils.now +":Hello!"+name)
        //使用包对象的方法
        def packageObjSay = println(now +":Hello!"+name)
        //父类包的包对象 在子包下都可以直接访问
        def prentObjSay = println(nowTime +":Hello!"+name )
      }

      class Cinner{
        def compare(b:B):Boolean = {
            b.age > 19
        }
      }
    }

    //Couter在a.b下面
    class Couter{
      def compare(b:B):Boolean = {
        //b.age //这样就访问不到 因为类Couter不在a.b.c包内
        b.height > 180 // 因为height的可见范围是a.b下面
      }
    }
  }
  // W的包路径是a
  class W{
    def say = println(a.b.nowTime) // 如果不在a.b(包含)下的类就不能直接使用nowTime访问包对象的field和方法 必须要加上路径名称才能访问
  }
}

/**
  * 包冲突
  */
package a{
  package b{
    package d{
      class D{
        def say = {
           // collection实际是在scala.collection,因为scala隐身引入了scal._ 所以这个省略了
           //val buf = new collection.mutable.ArrayBuffer[String]
           val buf = _root_.scala.collection.mutable.ArrayBuffer[String]("1")
        }
      }
    }

    /**
      * 如果这个时候在a.b下增加子包collection 那么class D中就会引用com.aralbox.p.a.b.collection
      * 在Java中,这个问题不会发生,因为包名总是绝对的
      * 但是在Scala中,包名是相对的,就像内部类的名称一样。
      * 内部类通常不会遇到这个问题,因为所有代码都在同一个文件当中,由负责该文件的人直接控制。
      * 但是包不一样,任何人都可以在任何时候向任何包添加内容
      * 解决方法一: 使用绝对包名,以_root_
      *           _root_.scala.collection.mutable.ArrayBuffer[String]
      * 解决方法二: "串联式"包语句
      *
    */
    package collection{

    }
  }
}

/**
  * "串联式"包语句
  */
package a.b.d{ // 对于类G来说 a、a.b包下的成员在这里就不可见
  package g{
    class G{
      def say = {
        //这样的包语句限定了可见的成员。现在com.aralbox.p.a.b.collection包不再能够以collection访问到了
        val buf = new collection.mutable.ArrayBuffer[String]
        buf + "a"
        buf +: "c"
      }
    }
  }
}

 3、包引用

/**
  * 引入语句
  * 1、_通配符 这和Java中的通配符*一样。在Scala中,*是合法的标识符。你完全可以定义com.horstmann.*.people这样的包,但请别这样做
  * 2、隐式引入 每个Scala程序都隐式地以如下代码开始
  *   import java.lang._
      import scala._
      import Predef._
  * 3、选取器HashMap =>_将隐藏某个成员而不是重命名它
  * 4、List => JavaList //重名List 为 JavaList
  */
import java.awt._
import java.util.{
       HashMap => _,
       List => JavaList
       }

 

 参考 http://www.cnblogs.com/sunddenly/p/4436897.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值