跳转到内容

Scala/导入

来自维基教科书,开放的书籍,为开放的世界

Scala 中的导入机制允许更直接地引用不同的实体,例如包、类、对象、实例、字段和方法。与 Java 或 C++ 相比,Scala 中导入代码的概念更加灵活。

  • 导入语句可以位于任何地方。它可以位于类的开头,在类或对象内部,或在方法或块内部。
  • 在导入时,成员可以被重命名或隐藏。
  • 包、类或对象可以被导入到当前作用域中。

导入

[edit | edit source]

任何导入都是使用关键字 "import" 定义的。一个导入包含在包中的对象的简单示例

package p1 {
  class A
}
object B {
  val x = new p1.A
  import p1.A
  val y = new A
}

在第 1-3 行中,声明了一个名为 "p1" 的包,其中包含一个名为 "A" 的类。在第 4-8 行中,定义了一个名为 "B" 的对象。在第 5 行中,一个名为 "x" 的值被赋值为类 "A" 的一个新实例,使用 "p1.A" 作为类 "A" 的完整标识符。在第 6 行中,使用关键字 "import",后跟标识符 "p1.A"。 "import" 声明使作用域中所有后续实体能够直接引用声明中标识符的最后一部分,这里是指类 "A"。在第七行中,直接引用类 "A",无需使用其完整标识符。

可以导入的实体包括对象成员,例如字段和方法

import math.Pi
import math.round

println("Pi is: " + Pi) //Prints "Pi is: 3.141592653589793".
println("Pi rounded is: " + round(Pi)) //Prints "Pi rounded is: 3".

在第一行中,导入对象 "math" 的名为 "Pi" 的字段,使其可用于导入声明之后的实体。在第二行中,同样导入对象 "math" 的名为 "round" 的方法。在第四行和第五行中,直接引用 "Pi" 和 "round",无需使用通常所需的标识符 "math.Pi" 和 "math.round"。

实例的成员也可以导入

class Cube(val a:Double)
def volume(cube:Cube) = {
  import cube.a
  a*a*a
}
val cube1 = new Cube(4)
println("The volume of cube1 is: " + volume(cube1)) //Prints "The volume of cube1 is: 64.0".

在第一行中,声明了一个名为 "Cube" 的类,其中包含一个名为 "a" 的值,表示边长。在第 2-5 行中,定义了一个计算立方体体积的方法。在第 3 行中,导入参数名为 "cube" 的字段 "a",在第 4 行中直接引用 "a"。在第 6 行中实例化一个新的立方体,在第 7 行中打印其体积。

包也可以导入

package p1.p2 {
  class A
}

import p1.p2

val a = new p2.A

在前 3 行中,声明了两个嵌套的包,名为 "p1" 和 "p2",其中 "p2" 包含一个名为 "A" 的类。在第五行中,导入 "p2"。在第七行中,直接引用 "p2",无需使用 "p1.p2" 来限定它。

您可以按照以下方式从一个包中导入多个类。

 import math.{Pi,round}

在单个导入语句中从 math 包导入 math.Pi 和 math.round 类。

通配符

[edit | edit source]

_ 字符在 Scala 中用作通配符。它类似于 Java 中的 * 字符。在下面的示例中,从 math 包导入所有内容。

 import math._
 println("Pi is: " + Pi) //Prints "Pi is: 3.141592653589793".
 println("Pi rounded is: " + round(Pi)) //Prints "Pi rounded is: 3".

导入选择子句

[edit | edit source]

重命名

[edit | edit source]

为了避免命名空间冲突,您可能需要在导入到作用域时重命名成员。在下面的示例中,Pi 重命名为 myPi,round 重命名为 myRound,它们从 math 包中导入,这样就不会与对象中的本地 Pi 和 round 成员发生冲突。

import math.{Pi => myPi,round => myRound}
object myMaths extends App {
  val Pi = 3.1 
  val round = TRUE
  println("Pi is: " + myPi) //Prints "Pi is: 3.141592653589793".
  println("Pi rounded is: " + myRound(myPi)) //Prints "Pi rounded is: 3".
}

隐藏

[edit | edit source]

Scala 提供了一个选项,允许您在从同一个包中导入其他成员时,隐藏一个或多个类。

import math.{Pi => _, _}
object myMaths extends App {
  println("Pi is: " + Pi) // Error, Pi is hidden
}

在上面的示例中,隐藏了 Pi,而从 math 包中导入的其余所有内容都导入到了作用域中。访问示例中的 Pi 会导致错误,因为 Pi 在导入时被隐藏了。

限制范围

[edit | edit source]

您可以在任何地方使用导入语句,这可以让您控制导入成员的作用域。

您可以在包的顶部使用导入语句。

package importTesting
import math.Pi
class test1 {
	def printPi {
		println("Pi is: " + Pi) //Successful
	}
}

class test2 {
	def printMyPi {
		println("Pi is :" + Pi) //Successful
	}
}

在上面的示例中,math.pi 在包的顶部被导入,math.pi 的作用域在整个包中。因此,它可以在包中所有类中使用。

您可以在类内部使用导入语句。

package importTesting
class test1 {
	import math.Pi
	def printPi {
		println("Pi is: " + Pi) //Successful
	}
}

class test2 {
	def printMyPi {
		println("Pi is :" + Pi) //Fail as the scope of Pi is limited to class test1
	}
}

在上面的示例中,math.pi 在类 test1 中被导入,Pi 的作用域被限制在类 test1 内部。无法从类 test2 中访问它。

您可以在类的某个方法内部使用导入语句,并将作用域限制到该成员。

package importTesting
class test1 {
	def printPi {
		import math.Pi
		println("Pi is: " + Pi) //Successful
	}

	def printMyPi {
		println("Pi is :" + Pi) //Fail as the scope of Pi is limited to the method
	}
}

隐式导入

[edit | edit source]
华夏公益教科书