如何对单例对象使用 import 语句

How to use import statement with singleton objects

下面的示例来自 Akka 的 Hello World 项目,根据给定的说明下载 here

示例代码在 AkkaQuickstart.scala 文件中。 classes Greeter 和 Printer 以及具有相同名称的对象都在包 com.example.

下的同一个文件中

在class Greeter中,有两个import语句:

import Greeter._
import Printer._

当所有这些对象都在同一个包的同一个文件中定义时,为什么需要在 class Greeter 中导入 Greeter 和 Printer?它们是必需的,因为如果删除这些导入,代码将无法编译。

有关导入的 Scala 文档 here 说明如下:

"import clauses are for accessing members (classes, traits, functions, etc.) in other packages. An import clause is not required for accessing members of the same package." 但在下面的代码中,即使所有 classes 和对象都在同一个包中,也需要导入。为什么需要导入?

与class打印机类似,有以下导入语句:

import Printer._

任何有关此主题的指导将不胜感激。

完整的示例代码如下:

//#full-example
package com.example

import akka.actor.{ Actor, ActorLogging, ActorRef, ActorSystem, Props }

//#greeter-companion
//#greeter-messages

object Greeter {
  //#greeter-messages
  def props(message: String, printerActor: ActorRef): Props = Props(new 
  Greeter(message, printerActor))
  //#greeter-messages
  final case class WhoToGreet(who: String)
  case object Greet 
 }

//#greeter-messages
//#greeter-companion

//#greeter-actor
class Greeter(message: String, printerActor: ActorRef) extends Actor {
import Greeter._    //*why is import required here?*
import Printer._    //*why is import required here?*

var greeting = ""

def receive = {
  case WhoToGreet(who) =>
    greeting = message + ", " + who
    case Greet           =>
    //#greeter-send-message
    printerActor ! Greeting(greeting)
    //#greeter-send-message
}

}
//#greeter-actor

//#printer-companion
//#printer-messages
object Printer {
  //#printer-messages
  def props: Props = Props[Printer]
  //#printer-messages
  final case class Greeting(greeting: String)
}
//#printer-messages
//#printer-companion

//#printer-actor
class Printer extends Actor with ActorLogging {
  import Printer._    //why is import required here?

  def receive = {
    case Greeting(greeting) =>
      log.info("Greeting received (from " + sender() + "): " +         
greeting)
  }
}
//#printer-actor

//#main-class
object AkkaQuickstart extends App {
  import Greeter._    //why is import required here?

  // Create the 'helloAkka' actor system
  val system: ActorSystem = ActorSystem("helloAkka")

  //#create-actors
  // Create the printer actor
  val printer: ActorRef = system.actorOf(Printer.props, "printerActor")

  // Create the 'greeter' actors
  val howdyGreeter: ActorRef =
    system.actorOf(Greeter.props("Howdy", printer), "howdyGreeter")
  val helloGreeter: ActorRef =
    system.actorOf(Greeter.props("Hello", printer), "helloGreeter")
  val goodDayGreeter: ActorRef =
    system.actorOf(Greeter.props("Good day", printer), 
  "goodDayGreeter")
  //#create-actors

  //#main-send-messages
  howdyGreeter ! WhoToGreet("Akka")
  howdyGreeter ! Greet

  howdyGreeter ! WhoToGreet("Lightbend")
  howdyGreeter ! Greet

  helloGreeter ! WhoToGreet("Scala")
  helloGreeter ! Greet

  goodDayGreeter ! WhoToGreet("Play")
  goodDayGreeter ! Greet
  //#main-send-messages
 }
 //#main-class
 //#full-example

如果没有这两个导入,我们必须完全限定我们在 GreeterPrinter 单例对象中访问的成员,就像这样

class Greeter(message: String, printerActor: ActorRef) extends Actor {
  var greeting = ""

  def receive: PartialFunction[Any, Unit] = {
    case Greeter.WhoToGreet(who) =>
      greeting = message + ", " + who
    case Greeter.Greet           =>
      printerActor ! Printer.Greeting(greeting)
  }
}

所以在 call-site

有点冗长
Greeter.WhoToGreet(who)
Greeter.Greet
Printer.Greeting(greeting)

相对于

import Greeter._ 
import Printer._    

WhoToGreet(who)
Greet
Greeting(greeting)

符号 import Greeter._object Greeter 的所有成员纳入范围,而不是包的成员。