如何用其他方法设置局部变量

时间:2018-08-08 12:12:23

标签: scala

是否可以在scala的子类中设置一个在方法中具有作用域的变量?

为什么我需要在下面的代码片段中进行解释:

abstract class SuperTask {
  def doWork():Unit = {
     var taskData:Option[TaskData] = None
     try {
        _actualWork() 
     }
     catch {
      //  catch exception and do reporting using taskData variable
     } 
  }

  protected def _actualWork(): Unit
}

class FunTask extends SuperTask {
    override def _actualWork(): Unit = {
       //This will have data for taskData
       //PROBLEM is how to set taskData of parent class from here so that if this throws exception, I can do reporting from catch in doWork method.
    }
}

我想设置taskData变量的值,以便如果_actualWork失败,我可以进行适当的报告,重试等,这对于SuperTask类的所有子类都是通用的

我无法在taskData类级别定义SuperTask变量,因为它将被共享并且在并发情况下失败。

2 个答案:

答案 0 :(得分:1)

只需传递一个知道如何将taskData设置为_actualWork的闭包即可:

type TaskData = String

abstract class SuperTask {
  def doWork():Unit = {
    var taskData:Option[TaskData] = None
    try {
       _actualWork(td => taskData = td) 
    } catch {
      case _: Throwable => println("last task data: " + taskData)
    } 
  }

  protected def _actualWork(setTaskData: Option[TaskData] => Unit): Unit
}

object FunTask extends SuperTask {
  override def _actualWork(setTaskData: Option[TaskData] => Unit): Unit = {
    // No problem to set taskData of parent class from here:
    setTaskData(Some("Hello, world!"))
    throw new Error("error")
  }
}

如果现在在doWork上调用FunTask,从而设置taskData并抛出错误,则会得到以下输出:

FunTask.doWork() 
// output: last task data: Some(Hello, world!)

请注意,这只是“观察者”模式的一种非常便宜的变体,其中已注册的“观察者”的状态由一个局部变量组成,“通知”由对闭包{ }}。您也可以将一大堆适当的“观察者”传递到setTaskData方法中,以便他们可以监视_actualWork内部的情况。

答案 1 :(得分:0)

这是关于您留言下方我的最后评论:

_actualWork分成两个函数?第一个是Option[TaskData],第二个是_actualWork(taskData: Option[TaskData])

abstract class SuperTask {
  def doWork():Unit = {
     val taskData:Option[TaskData] = getData
     try {
        _actualWork(taskData) 
     }
     catch {
      //  catch exception and do reporting using taskData variable
     } 
  }

  protected def getData(): Option[TaskData]
  protected def _actualWork(taskData: Option[TaskData]): Unit
}

class FunTask extends SuperTask {
    override def getData(): Option[TaskData] = Some(data)
    override def _actualWork(taskData: Option[TaskData]): Unit = {
       //do some work with taskData
    }
}