Modules and objects

Modules are a way to organize programs. They are interchangeable and pluggable pieces of code that have well-defined interfaces and hidden implementations. In Java, modules are organized in packages. In Scala, modules are objects; just like everything else. This means that they can be parameterized, extended, and passed as parameters, and so on.

Scala modules can provide requirements in order to be used.

Using modules

We already established that modules and objects are also unified in Scala. This means that we can pass an entire module around our application. It would be useful, however, to show what a module actually looks like. Here is an example:

trait Tick { 
  trait Ticker { 
    def count(): Int 
    def tick(): Unit 
  } 
  def ticker: Ticker 
}

Here, Tick is just an interface to one of our modules. The following is its implementation:

trait TickUser extends Tick { 
  class TickUserImpl extends Ticker { 
    var curr = 0 
    
    override def count(): Int = curr 

    override def tick(): Unit = { 
      curr = curr + 1 
    } 
  } 
  object ticker extends TickUserImpl 
}

The TickUser trait is an actual module. It implements Tick and contains the code hidden inside it. We create a singleton object that will carry the implementation. Note how the name in the object is the same as the method in Tick. This would cover the need to implement it when mixing in the trait.

Similarly, we can define another interface and an implementation as follows:

trait Alarm { 
  trait Alarmer { 
    def trigger(): Unit 
  } 
  def alarm: Alarmer 
}

The implementation will be this:

trait AlarmUser extends Alarm with Tick { 
  class AlarmUserImpl extends Alarmer { 
    override def trigger(): Unit = { 
      if (ticker.count() % 10 == 0) { 
        System.out.println(s"Alarm triggered at ${ticker.count()}!") 
      } 
    } 
  } 
  object alarm extends AlarmUserImpl 
}

What is interesting here is that we extended both modules in the AlarmUser one. This shows how modules could be made to be dependent on each other. Finally, we can use our modules as follows:

object ModuleDemo extends AlarmUser with TickUser { 
  def main(args: Array[String]): Unit = { 
    System.out.println("Running the ticker. Should trigger the alarm every 10 times.") 
    (1 to 100).foreach { 
      case i => 
        ticker.tick() 
        alarm.trigger() 
    } 
  } 
}

In order for ModuleDemo to use the AlarmUser module, it is also required by the compiler to mix in TickUser or any module that mixes in Tick. This provides a possibility to plug in a different functionality.

The output of the program will be this:

Running the ticker. Should trigger the alarm every 10 times. 
Alarm triggered at 10! 
Alarm triggered at 20! 
Alarm triggered at 30! 
Alarm triggered at 40! 
Alarm triggered at 50! 
Alarm triggered at 60! 
Alarm triggered at 70! 
Alarm triggered at 80! 
Alarm triggered at 90! 
Alarm triggered at 100!

Note

Modules in Scala can be passed as any other object. They are extendable, interchangeable, and their implementation is hidden.

..................Content has been hidden....................

You can't read the all page of ebook, please click here login for view all page.
Reset
3.144.47.218