A package is a special object that defines a set of member classes and objects. The Scala package lets you segregate code into logical groupings or namespaces so that they don’t conflict with each other. In Java you’re only allowed to have package at the top of the .java file, and the declaration defines the scope across the file. Scala takes a different approach for packaging. It combines Java’s declaration approach with C#’s scoped approach. You can still use the traditional Java approach and define package at the top of the Scala file, or use a scoping approach, as demonstrated in the following listing.
- Listing 3.1 Declaring packages using the scoping approach
- package com {
- package scalainaction {
- package mongo {
- import com.mongodb.Mongo
- class MongoClient(val host:String, val port:Int) {
- require(host != null, "You have to provide a host name")
- private val underlying = new Mongo(host, port)
- def this() = this("127.0.0.1", 27017)
- }
- }
- }
- }
- package com.scalainaction.mongo
- import com.mongodb.Mongo
- class MongoClient(val host:String, val port:Int) {
- require(host != null, "You have to provide a host name")
- private val underlying = new Mongo(host, port)
- def this() = this("127.0.0.1", 27017)
- }
- package com.scalainaction.mongo {
- import com.mongodb.Mongo
- class MongoClient(val host:String, val port:Int) {
- require(host != null, "You have to provide a host name")
- private val underlying = new Mongo(host, port)
- def this() = this("127.0.0.1", 27017)
- }
- }
One more interesting point to note here is that Scala package declaration doesn’t have to match the folder structure of your filesystem. You’re free to declare multiple packages in the same file:
- package com.persistence {
- package mongo {
- class MongoClient
- }
- package riak {
- class RiakClient
- }
- package hadoop {
- class HadoopClient
- }
- }
Scala imports
You’ve already seen some examples of import in previous chapters, but I haven’t discussed it. At first glance, the Scala import looks similar to Java imports, and it’s true they’re similar, but Scala adds some coolness to it. To import all the classes under the package com.mongodb, you have to declare the import as follows:
- import com.mongodb._
In this case you’re importing the Random class defined in the scala.util package in the Scala code block, and it’s lexically scoped inside the block and won’t be available outside it. Because the Scala package is automatically imported to all Scala programs, you could rewrite the block by relatively importing the util.Random class:
In Scala, when you import a package, Scala makes its members, including subpackages, available to you. To import members of a class, you have to put ._ after the class name:
Here you’re invoking the nanoTime method defined in the System class without a prefix because you’ve imported the members of the System class. This is similar to static imports in Java (Scala doesn’t have the static keyword). Because imports are relatively loaded, you could import the System class in the following way as well:
You could also list multiple imports separated by commas. Scala also lets you map a class name to another class name while importing—you’ll see an example of that soon.
There’s one handy feature of Scala import: it allows you to control the names that you import in your namespace, and in some cases it improves readability. In Java, for example, working with both java.util.Date andjava.sql.Date in the same file becomes confusing; in Scala you could easily remap java.sql.Date to solve the problem:
- import java.util.Date
- import java.sql.{Date => SqlDate}
- import RichConsole._
- val now = new Date
- p(now)
- val sqlDate = new SqlDate(now.getTime)
- p(sqlDate)
- import java.sql.{Date => _ }
To finish the functionality required for the first user story, you still need to add methods for creating and dropping the database. To achieve that you’ll add the methods shown in the following listing.
- Listing 3.2 Completed MongoClient
- package ch3
- import com.mongodb.Mongo
- import com.mongodb.DB
- class MongoClient(val host:String, val port:Int) {
- require(host != null, "You have to provide a host name")
- private val underlying = new Mongo(host, port)
- def this() = this("127.0.0.1", 27017)
- def dropDB(name:String) = underlying.dropDatabase(name)
- def createDB(name:String) = DB(underlying.getDB(name))
- def db(name:String) = DB(underlying.getDB(name))
- }
沒有留言:
張貼留言