使用 Scala trait 作为回调接口

Using Scala trait as a callback interface

我刚开始学习 scala,并尝试通过制作一个简单的应用程序 dicebot 来学习自己。

这是处理这个简单命令的简单应用程序。

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)

}

顺便说一句,在应用程序的第一部分,我想传递一个回调函数,它会在 Dice Bot 完成工作时被调用。

Dice.run(_command.tail, callback)

问题是..我不太确定要为 callback 参数传递什么。 如果这是 Java,我将定义一个如下所示的接口,但在 Scala 中,我不确定要使用什么。

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();
       }
   }

我从某处听说 trait 是接口,但我真的不明白。

trait BotInterface {
  def onReceiveResult(result: List[String]): List[String]
}

请教一下如何使用trait作为回调接口?

提前致谢! :)

如果您需要的是一个接受 List[String] 并返回 List[String] 的回调,则不需要 trait,您可以要求一个 函数:

def run(command: List[String], callback: List[String] => List[String]): List[String]

callback 在定义中使用了一点语法糖。它实际上被翻译成一个名为 Function1[List[String], List[String]] 的类型。

现在调用者可以使用匿名函数语法来传递实现:

run(List("1","2","3"), l => { 
  l.foreach(println)
  l
})

我们甚至可以使用 second 参数列表(这称为 currying)使它更漂亮一点:

def run(command: List[String])(callback: List[String] => List[String]): List[String]

现在我们有:

run(List("1","2","3")) { l =>
  l.foreach(println)
  l
}

如果您仍然确信自己想要一个 trait,它实际上与您在 Java:

中定义接口的方式非常相似
trait BotInterface {
  def onReceiveResult(result: List[String]): List[String]
}

def run(command: List[String], callback: BotInterface): List[String]

注意 Scala 中的特征可以有默认实现,类似于 Java 8 的默认方法:

trait BotInterface {
  def onReceiveResult(result: List[String]): List[String] = result.map(_.toLowerCase)
}

run 定义中,您需要调用 callback.onReceiveResult(list)