8.2 包
Scala 中包的声明, 命名规则和 Java 完全一样, 在此不再赘述.
只学习下与 Java 不同的地方
8.2.1 包语句
Java 的中的包的声明一般是通过 package x.y.z
来声明.
Scala 不仅仅支持 Java 的这种声明方式, 还支持另外一种更加灵活的方式:
package com{
package atguigu{
class Person{ // com.atguigu.Person
}
}
}
package com{
package atguigu{
package xx{
class Person{ // com.atguigu.xx.Person
}
}
}
}
说明:
- 一个文件中的多个类可以使用不同的包
- 包的结构将来也和文件夹结构没有必然联系了
- 如果一个文件的中的所有的类都属于同一个包, 最好使用 Java 提供的
顶部标记法 , 而实际情况也确实是这样是最普遍的做法.
8.2.2 包对象
在 Java 中, 我们的一些工具函数或者常量需要专门添加到一个所谓的类中. 这种做法主要是 JVM 的限制, 但其实并不是很好的选择.
如果能把这些东西添加到包中是更好的一种选择.
Scala 提供的
package com.atguigu.day04
package abc {
object Person {
def main(args: Array[String]): Unit = {
val p1 = new Person()
p1.say()
}
}
}
package object abc {
var A: Int = 3
def foo() = {
println("包对象中定义的函数...")
}
}
package abc {
class Person {
def say() = {
// 调用包对象中的属性和方法时, 直接调用即可, 不需要前缀
println(A)
foo()
}
}
}
说明:
在幕后, 包对象被编译成类, 名字就叫
package.class
, 放在相应的包下.本例中放在包
com.atguigu.day04.abc
中
8.2.3 包的可见性
在 Java 中,访问权限分为: public
,private
,protected
和默认
。在Scala 中,你可以通过类似的修饰符达到同样的效果。但是使用上有区别。
当方法访问权限为默认时,默认为
public
访问权限在 Scala 中没有
public
关键字,即不能用public
显式的修饰属性和方法。private
为私有权限,只在类的内部和伴生对象中可用关于伴生对象和伴生类的概念, 后面再细说
package com.atguigu.day04 /* 当在一个文件中, object 名和 class 名相同时 object 叫伴生对象, class 叫伴生类 */ object AccessTest { def main(args: Array[String]): Unit = { val test = new AccessTest // 伴生对象内部可以访问伴生类内部的私有属性和方法 println(test.a) } } class AccessTest{ private var a = 10 def foo(): Unit ={ println(a) } }
protected
为受保护权限,Scala 中受保护权限比 Java 中更严格,只能子类访问,同包无法访问。包访问权限 一般是属性私有了, 可以增加包访问权限, 然后包内的其他类也可以访问到了. 这点体现出来了 Scala 包相比 Java 的灵活性.
8.2.4 包的导入
Scala 中导包用的关键字仍然是import
Scala 导入的特点:
1. 在 Scala 中,import 语句可以出现在任何地方,并不仅限于文件顶部.
import语句的作用一直延伸到包含该语句的块末尾
这种语法的好处是:在需要时在引入包,缩小import 包的作用范围,提高效率
2. Scala 使用_
来导入一个包下的所有的类(Java 是*
)
3. 如果不想要某个包中全部的类, 而是其中的几个类, 可以采用选取器(大括号)
4. 类的重命名
如果引入的多个包中含有相同的类,那么可以将不需要的类进行重命名进行区分,这个就是重命名
package com.atguigu.day04
// Scala 提供的 HashMap
import scala.collection.mutable.HashMap
// 给 Java 的HashMap重命名为JavaHashMap
import java.util.{HashMap => JavaHashMap}
object PackDemo3 {
def main(args: Array[String]): Unit = {
// 使用重命名后的JavaHashMap
val map1 = new JavaHashMap[String, String]()
val map2 = new HashMap[String, String]()
}
}
5. 如果某个冲突的类根本就不会用到,那么这个类可以直接隐藏掉
package com.atguigu.day04
// 隐藏scala.collection.mutable.HashMap
import scala.collection.mutable.{HashMap => _, _}
import java.util._
//import java.util.{HashMap=>_, _}
object PackDemo3 {
def main(args: Array[String]): Unit = {
// 毫无疑问的指向了java.util.HashMap
val map2 = new HashMap[String, String]()
}
}
6. 隐式引入
下面 2 个包的所有类都被隐式引入:
import java.lang._
import scala._
和对象:
import scala.Predef._
Predef
对象中包含了类型、隐式转换以及在 Scala 中常用的一些方法。
所以,既然已经默认导入,那么无须任何前缀或者导入,就可以直接使用那些方法和隐式转换。
它们太方便了,以至于你开始相信它们是 Scala 的一部分,实际上它们是 Scala 标准库的一部分。
Predef
对象还提供了一些类型的别名,如 scala.collection.immutable.Set
和 scala.collection.immutable.Map
。
因此,当使用 Set
或者 Map
的时候,实际使用的是 Predef
中对它们的定义,它们分别指向它们在 scala.collection.immutable
包中的定义。