Chapter 13 《Packages and Imports

作者: liqing151 | 来源:发表于2018-06-21 19:38 被阅读11次

在大程序中,减少耦合是很重要的,耦合是指程序不同部分依赖其他部分的程度。低耦合能够减少局部修改对其它部分造成的影响。方法就是以模块化的风格来书写代码。本章就是利用包和引入来进行模块化风格的编程。


将代码放进包里
  • 有两种方式,

    • 1.第一种是在源码的最上方放入package语句。
    package.bobstore.navigation
    
      1. 第二种方式是类似于命名空间的方式,可以在一个文件中包含多个包的内容
    package bobsrockets {
    package navigation {
    // In package bobsrockets.navigation
    class Navigator
    package tests {
    // In package bobsrockets.navigation.tests
    class NavigatorSuite
    }
    }
    }
    

    代码按照包层次结构划分之后,编译器可知道在同一个包中的代码存在某种联系。访问同一个包的代码时,可以使用简短的,不带限定前缀的名称。

      1. 在使用命名空间方式的嵌套打包方法中,在包外可以访问到的作用域在保内也可以访问到。但是这种必须使用显示的嵌套打包。
    package bobsrockets {
    class Ship {}
    package fleets {
    class Fleet {
    // No need to say bobsrockets.Ship
    def addShip() = { new Ship }
    }
    }
    }
    

    如果每个文件只有一个包,包名在文件的顶部,那么不能访问包外的作用域。

    package bobsrockets {
    class Ship
    }
    package bobsrockets.fleets {class Fleet {
    // Doesn't compile! Ship is not in scope.
    def addShip() = { new Ship }
    }
    }
    

    是无效的。

      1. 如果嫌弃package的缩进太多,可以使用多个package子句但是不用花括号。
    package bobsrockets
    package fleets
    class Fleet {
    // No need to say bobsrockets.Ship
    def addShip() = { new Ship }
    }
    

    每个包都是顶层包__root__的成员。


引入
  • 1.可以使用import引入包和它的成员。可以出现在任何地方,可以引入任何值,甚至是一个对象的值。可以引入Object中的内容。_表示通配符,表示对所有成员的便捷引入。还可以引入包本身,例如import java.util.regex,可以方便使用regex.Pattern
    1. 引入还可以重命名用来隐藏引入的成员。
      import Fruits.{Apple => McIntosh, Orange}
      在代码中使用的时候可以使用McIntosh或者Fruits.Apple
      import Fruits{Apple => McIntosh, _}
      引入Fruits的所有成员,将Apple进行重命名
      import Fruits{Pear => _, _}
      引入除了PearFruits的所有成员。其实将Pear重命名为_,其实也就是隐去了这个方法。如果要在引入语句中引入所有的成员,用_表示的时候,必须将_放在引入列表的最后。

隐式引入
    1. Scala对每个程序都隐式的添加了一些引入。
    import java.lang._ // everything in the java.lang package
    import scala._ // everything in the scala package
    import Predef._ // everything in the Predef object
    
    Predef对象定义了许多类型,方法以及隐式转换的定义。对着三个引入做了处理,后引入的会遮挡前面的。StringBuilder同时出现在langscala包中,但是会处理称为scala标准库中的StringBuilder

访问修饰符
  • 访问修饰符可以作用在包、类或者对象的成员上。访问修饰符将对成员的访问限定在特定的代码区域。
    private成员:只对包含该成员定义的类或者对象可见。
    protected成员:只对包含该成员定义的类或者对象以及子类中可见。
    默认的就是public成员。公共成员对任何代码都是可见的。

限定词
  • 可以使用限定词对Scala中的访问修饰符进行增强,对成员的可见性做非常细粒度的控制,非常灵活的定义成员或者类的可见性,可以将可见性分割为特定包可见。
    private[this]:仅对当前对象可见,对象私有的,只能通过当前对象this进行访问。在别的对象内是不能够访问的。隔离了其他对象对该对象的修改。
 class C {
   private[this] val num = 123
   def +(that: C) = num + that.num // compile error
}

private[X]或者protected[X]表示上至X都可见,比如X是包名,则在这个包里是可见的。
protected[X]表示在该X中或者该类的子类中都是可见的。


可见性和伴生对象
    1. 类可以访问伴生对象的所有私有成员,对象可以访问伴生类的所有私有成员。类访问伴生对象的私有成员时,使用ObjectA.privateVal
    1. 在伴生对象的成员中一般不使用protected进行修饰,因为伴生对象没有子类。

包对象
    1. 在包中可以放置类、特质以及孤立对象等。任何能放在类级别的定义都可以放在包级别。具体做法是将这些定义放在包对象中,每一个包都有一个包对象,在其中的定义都会被当作是这个包的成员。
    1. 可以在包对象中放入一些通用的工具方法。showFruit可以像包中的其他成员一样被引入被使用。
// In file bobsdelights/package.scala
package object bobsdelights {
def showFruit(fruit: Fruit) = {
import fruit._
println(name + "s are " + color)
}
}
// In file PrintMenu.scala
package printmenu
import bobsdelights.Fruits
import bobsdelights.showFruit

包对象会编译成为package.class的类文件,位于该包的对应目录下。包对象的源码一般放在对应的包中,名为package.scala文件中。

相关文章

网友评论

    本文标题:Chapter 13 《Packages and Imports

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