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!" } }