官术网_书友最值得收藏!

  • Scala Design Patterns
  • Ivan Nikolov
  • 487字
  • 2021-07-16 12:57:28

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.

主站蜘蛛池模板: 大足县| 陇西县| 喀什市| 遵化市| 上犹县| 甘孜县| 东乌| 禹州市| 镇雄县| 略阳县| 张家口市| 五指山市| 竹溪县| 兴安盟| 桐乡市| 石家庄市| 汉中市| 宝兴县| 邵武市| 武功县| 余江县| 霞浦县| 西宁市| 永兴县| 晋江市| 缙云县| 区。| 开封市| 遵义县| 邳州市| 建湖县| 隆回县| 普宁市| 咸宁市| 和龙市| 新昌县| 高邑县| 瑞安市| 莎车县| 同德县| 灵宝市|