Reputation: 709
I just started learning scala and trying learn myself by making a simple application, dicebot.
Here's the simple application which process this simple command.
CommandRouter().run("dice roll 3d4")
package com.kwoolytech.kwoolybot
case class CommandRouter() {
def run(command: String): List[String] = {
val _command = command.split("\\s+").toList
commandArray.head match {
case "dice" => Dice.run(_command.tail)
case _ => List[]
}
}
}
package com.kwoolytech.kwoolybot
case class Dice() extends Bot {
def run(command: List[String]): List[String] = {
command.head match {
case "roll" => roll(_command.tail)
case _ => List[]
}
}
private def roll(command: Array[String]): List[String] = {
val rollCmdPattern = "([0-9]+)d([0-9]+)".r
command.head match {
case rollCmdPattern(numTry, diceSize) => rollDice(numTry, diceSize)
case _ => List[]
}
}
private def rollDice(numTry: Int, diceSize: Int): List[String] = {
(1 to numTry).map { x => scala.util.Random.nextInt(diceSize) + 1})
}.toList.map(_.toString)
}
Btw, at the very first part of the application, I want to pass over a callback function, which will get called when the Dice Bot done its work.
Dice.run(_command.tail, callback)
The thing is.. I am not quite sure what to pass over for the callback parameter. If this was Java, I will define a interface like below but in scala, I am not really sure what to use.
interface KwoolyHttpCallback {
void onWeatherJsonDataReceived(String result);
void onWeatherBitmapDataReceived(Bitmap result);
}
private void initializeKwoolyHttpCallbackFunction() {
httpClientCallback = new KwoolyHttpCallback() {
@Override
public void onWeatherJsonDataReceived(String result) {
try {
dataModel.setWeatherJsonData(result);
queryWeatherBitmapData();
} catch (Exception e) {
Log.e(getClass().getName(), "Exception: ");
e.printStackTrace();
}
}
I heard from somewhere that the trait is the interface but I am really not getting it.
trait BotInterface {
def onReceiveResult(result: List[String]): List[String]
}
Could you please teach me how to use the trait as a callback interface?
Thanks in advance! :)
Upvotes: 0
Views: 357
Reputation: 149538
If what you need is a callback taking a List[String]
and returning a List[String]
, there's no need for a trait, you can require a function:
def run(command: List[String], callback: List[String] => List[String]): List[String]
The callback
is using a little syntax sugar for the definition. It actually gets translated into a type named Function1[List[String], List[String]]
.
Now callers can use anonymous function syntax to pass in an implementation:
run(List("1","2","3"), l => {
l.foreach(println)
l
})
We can even make this a little bit prettier by using a second parameter list (this is called currying):
def run(command: List[String])(callback: List[String] => List[String]): List[String]
And now we have:
run(List("1","2","3")) { l =>
l.foreach(println)
l
}
If you're still convinced that you want a trait
, it's actually pretty similar to how you'd define an interface in Java:
trait BotInterface {
def onReceiveResult(result: List[String]): List[String]
}
def run(command: List[String], callback: BotInterface): List[String]
Note that traits in Scala can have default implementations, similar to Java 8's default methods:
trait BotInterface {
def onReceiveResult(result: List[String]): List[String] = result.map(_.toLowerCase)
}
And inside the run
definition you'll need to call callback.onReceiveResult(list)
Upvotes: 1