Sometimes code is common to all the classes of a specific package (e.g.: conversions between objects, custom logs, shared operations, etc). Our lovely Java doesn’t seem to have a convenient way of declaring code as part of a package, rather than just a class….but FEAR NO MORE! Let’s see how we can this in Scala using package objects.
First step is to define the shared package code.
// in file girlcoding/tutorial/package.scala
package girlcoding
package object tutorial {
def customLog(msg: String) {
println(s"Customised package log: $msg")
}
}
The compiler will extract and compile the package code into a package.class file: the convention is to be consistent with it and to put its source code in a package.scala file as well — but you are not forced to!
We are now ready to use this shared code in all the girlcoding.tutorial classes:
// in file girlcoding/tutorial/MyClassA.scala
package girlcoding.tutorial
class MyClassA {
def saySomething(msg: String) = customLog(msg)
}
What if we what to use it in sub packages as well?
// in file girlcoding/tutorial/whatever/MyClassB.scala
package girlcoding.tutorial
package whatever
// package girlcoding.tutorial.whatever doesn’t compile!
class MyClassB {
def saySomethingElse(msg: String) = customLog(msg)
}
Note that if we use the declaration package girlcoding.tutorial.whatever (see line 4), it doesn’t work: to fix it, we need to declare a dependency on package girlcoding.tutorial as well (see lines 2-3).
This simple main class is checking that everything is working together as expected:
import girlcoding.tutorial.MyClassA
import girlcoding.tutorial.whatever.MyClassB
object MyMain {
def main(args: Array[String]) {
val myClassA = new MyClassA
myClassA.saySomething("Hello from class A")
// it prints: "Customised package message: Hello from class A"
val myClassB = new MyClassB
myClassB.saySomethingElse("Yo, I am way cooler than class A!")
// it prints: "Customised package message: Yo, I am way cooler than class A!"
}
}