Chapter 13 《Packages and Imports
2018-06-21 本文已影响11人
liqing151
在大程序中,减少耦合是很重要的,耦合是指程序不同部分依赖其他部分的程度。低耦合能够减少局部修改对其它部分造成的影响。方法就是以模块化的风格来书写代码。本章就是利用包和引入来进行模块化风格的编程。
将代码放进包里
-
有两种方式,
- 1.第一种是在源码的最上方放入
package
语句。
package.bobstore.navigation
- 第二种方式是类似于命名空间的方式,可以在一个文件中包含多个包的内容
package bobsrockets { package navigation { // In package bobsrockets.navigation class Navigator package tests { // In package bobsrockets.navigation.tests class NavigatorSuite } } }
代码按照包层次结构划分之后,编译器可知道在同一个包中的代码存在某种联系。访问同一个包的代码时,可以使用简短的,不带限定前缀的名称。
- 在使用命名空间方式的嵌套打包方法中,在包外可以访问到的作用域在保内也可以访问到。但是这种必须使用显示的嵌套打包。
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 } } }
是无效的。
- 如果嫌弃
package
的缩进太多,可以使用多个package
子句但是不用花括号。
- 如果嫌弃
package bobsrockets package fleets class Fleet { // No need to say bobsrockets.Ship def addShip() = { new Ship } }
每个包都是顶层包
__root__
的成员。 - 1.第一种是在源码的最上方放入
引入
- 1.可以使用
import
引入包和它的成员。可以出现在任何地方,可以引入任何值,甚至是一个对象的值。可以引入Object
中的内容。_
表示通配符,表示对所有成员的便捷引入。还可以引入包本身,例如import java.util.regex
,可以方便使用regex.Pattern
- 引入还可以重命名用来隐藏引入的成员。
import Fruits.{Apple => McIntosh, Orange}
在代码中使用的时候可以使用McIntosh
或者Fruits.Apple
import Fruits{Apple => McIntosh, _}
引入Fruits
的所有成员,将Apple
进行重命名
import Fruits{Pear => _, _}
引入除了Pear
的Fruits
的所有成员。其实将Pear
重命名为_
,其实也就是隐去了这个方法。如果要在引入语句中引入所有的成员,用_
表示的时候,必须将_
放在引入列表的最后。
- 引入还可以重命名用来隐藏引入的成员。
隐式引入
-
-
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
同时出现在lang
和scala
包中,但是会处理称为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
中或者该类的子类中都是可见的。
可见性和伴生对象
- 类可以访问伴生对象的所有私有成员,对象可以访问伴生类的所有私有成员。类访问伴生对象的私有成员时,使用
ObjectA.privateVal
。
- 类可以访问伴生对象的所有私有成员,对象可以访问伴生类的所有私有成员。类访问伴生对象的私有成员时,使用
- 在伴生对象的成员中一般不使用
protected
进行修饰,因为伴生对象没有子类。
- 在伴生对象的成员中一般不使用
包对象
- 在包中可以放置类、特质以及孤立对象等。任何能放在类级别的定义都可以放在包级别。具体做法是将这些定义放在包对象中,每一个包都有一个包对象,在其中的定义都会被当作是这个包的成员。
- 可以在包对象中放入一些通用的工具方法。
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
文件中。