【问题标题】:How to set a local variable in other method如何在其他方法中设置局部变量
【发布时间】:2019-01-15 16:55:03
【问题描述】:

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

为什么我需要在下面的代码 sn-p 中解释:

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 类的所有子类都是通用的。

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

【问题讨论】:

  • 我不确定我是否理解正确,但是您可以更改_actualWork() 函数的签名并将myObject 传递给它。比如:`try {_actualWork(myObject) } catch {}`
  • @dyrkin 不,这是不可能的:stackoverflow.com/q/9535821/1610034
  • 那么,您要从_actualWorktaskData 分配新值吗?
  • @dyrkin 是的,我想设置taskData 变量,这样如果_actualWork 失败,我可以进行适当的报告、重试等,这对于SuperTask 的所有子类都是通用的.
  • 这种听起来像XY problem。您能否详细说明您想要实现的目标?

标签: scala


【解决方案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")
  }
}

如果您现在在 FunTask 上调用 doWork,这会设置 taskData 并引发错误,您会得到以下输出:

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

请注意,这只是“观察者”模式的一个非常便宜的变体,其中您注册的“观察者”的状态由一个局部变量组成,而“通知”由闭包setTaskData的调用组成.您也可以将一大堆适当的“观察者”传递给 _actualWork 方法,以便他们可以监控 _actualWork 内部发生的事情。

【讨论】:

  • 谢谢,这对我有用。是否有任何好的链接显示 scala 中这种类型的观察者模式的示例?
  • @Saurabh 不是。这只是一个非常模糊的类比。只有一些类似对象的实体(在这种情况下是一个闭包),你可以对它说“看,有些东西改变了!”。这就是它的全部......
【解决方案2】:

关于我在您留言下方的最后一条评论:

_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
    }
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-03
    • 2022-11-15
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多