07. Packages and Imports - RobertMakyla/scalaWiki GitHub Wiki
KEY POINTS:
- Packages nest just like inner classes.
- Package paths are not absolute.
- A chain x.y.z in a package clause leaves the intermediate both packages 'x' and 'x.y' invisible.
- Package statements without braces at the top of the file extend to the entire file.
- A package object can hold functions and variables.
- Import statements can import packages, classes, and objects.
- Import statements can be anywhere.
- Import statements can rename and hide members.
- java.lang, scala, and Predef are always imported.
Package Visibility
- public - member not labeled private or protected is by default public
- private - accessible for all instances of current class
- protected - accessible only for all instances of current class and subclasses. Unlike in Java, it's not accessible in the package outside heritage tree
- unlike Java, there's no fourth default access modifier
class Person {
private[people] def sth = 0 // visible For people pkg
private[c] def sth = 0 // visible For c pkg
private[this] def sth = 0 // visible For This Instance of Person ONLY
private[MyClass] def sth = 0 // visible For instances of MyClass
private[Person] def sth = 0 // visible For all instances Of Person
private def sth = 0 // (the same)
}
Packages
package a {
package b {
package c {
class Employee // accessible with a.b.c.Employee
}
}
}
In scala, the Employee.scala file doesn't have to be in a/b/c directory
In one scala file (Employee.scala), there may be many package structures
package a {
package b {
package c {
class Employee
}
}
}
package org {
package bigjava {
class Counter {}
}
}
Scope Rules
package a {
package b {
package c {
object Utils {
def increment(value: Int) = value * 2
}
package d {
class Employee { //everything from parent packages is accessible
def raiseSalary(current:Int) = Utils.increment(current)
}
}
}
}
}
So I can use everything under it directly (no need to write scala.collection...)
val subordinates = new collection.mutable.ArrayBuffer[Employee]
If I declare 'package collection {}' anywhere above usage of 'new collection.mutable.ArrayBuffer[Employee]' it will not compile because compiler will first consider my custom 'collection' (not scala.collection) and there's no 'mutable' package in 'collection' declared by me
Workaround:
val subordinates = new scala.collection.mutable.ArrayBuffer[Employee]
// or
val subordinates = new _root_.scala.collection.mutable.ArrayBuffer[Employee]
Chained packages
package a.b.c {
// members of 'a' or 'a.b' are NOT visible here
}
Top-of-File Notation (instead of nested notation)
It is PREFERRED NOTATION cause in most cases all the code in file belongs to 1 pkg
package a.b.c
package people
class Person {} // Note that I can also refer to content of a.b.c
is equivalent to
package a.b.c {
package people {
class Person {} // Note that I can also refer to content of a.b.c
// Until the end of the file
}
}
Package Objects
A package can contain classes, objects, and traits, but not the definitions of functions or variables
This is a limitation that comes from JVM
However, in scala each package can have one package object (defined in parent pkg, name the same as pkg)
package world
package object people {
val defaultName = "John Q. Public"
}
package people {
class Person {
var name = defaultName // A constant from the package
}
}
Outside 'people' package it is accessible as: world.people.defaultName
Imports can be anywhere
class Manager {
import scala.collection.mutable._
val subordinates = new ArrayBuffer[Employee]
}
Aliases and Hiding members
import java.awt.{Color, Font} // importing two elements and not the whole package
import collection.mutable.{HashMap => MyMap} // MyMap is an alias to HashMap
val m = MyMap(1->11, 2->22)
import scala.collection.mutable._ // plain HashMap is a scala.collection.mutable.HashMap
import java.util.{HashMap => _, _} // importing all (_) except HashMap (HashMap => _)
import scala.collection.mutable._
Implicit Imports
It's like java.lang in Java
import java.lang._
import scala._
import Predef._ //this could be under scala, but Predef
//... was introduced before Scala had package
java.lang, scala, and Predef packages are always imported
scala.StringBuilder overrides java.lang.StringBuilder instead of conflicting with it.