Scala 未初始化变量(块不能包含声明)

Scala 未初始化变量(块不能包含声明),scala,object,variables,Scala,Object,Variables,遵循以下准则,尤其是本准则: object Control { def using[A <: { def close(): Unit }, B](resource: A)(f: A => B): B = try { f(resource) } finally { resource.close() } } ... using(io.Source.fromFile("example.txt")) { source =>

遵循以下准则,尤其是本准则:

object Control {
  def using[A <: { def close(): Unit }, B](resource: A)(f: A => B): B =
    try {
      f(resource)
      } finally {
        resource.close()
    }
}

...

using(io.Source.fromFile("example.txt")) { source => { .....
object Control
{
   def using[A <: { def close(): Unit }, B](opener: String => A)(name:String)(func: A => B): Unit =
   {
      var resource:A
                // ^ Error: 'Block cannot contain declarations'

      try
      {
         resource = opener(name)
         func(resource)
      }
      catch
      {
         case e: (_) => println(s"Failed to open resource '${name}' (${e})")
      }
      finally
      {
         println("Closing file ...")
         resource.close()
      }
   }
}
因此,我定义了一个方法,它将一个opener函数作为第一个参数,该函数接收一个字符串,并返回一个实现close的对象、一个用于opener函数的字符串和一个处理函数

但是,它不允许我在try-catch块之外声明资源变量,这样我就可以在finally块中访问它。如果我像var-resource:A=openername一样将其放入try块中,它将起作用,但是我无法到达finally块中的资源


我怎样才能解决它?我不得不说,我仍然是Scala的初学者,所以我在这里有点迷茫。

这里有一个修改过的示例,您也可以运行:

请注意,不管您怎么想,这不会引发NullPointerException。你可以阅读更多关于它的内容

我还添加了一些您可能感兴趣的内容:

显式导入scala.language.reflectiveCalls:结构类型在运行时通过JVM上的反射调用实现,至少编译器会在编译时告诉您一个警告

将{def close:Unit}命名为某种东西,使它在使用type的方法签名中更具可读性

使用非致命事件处理异常,您可以了解更多有关它的信息


谢谢,这就成功了。我尝试了初始化var resource=null的几种变体,但似乎都不起作用。这一个是:案例e:=>和案例NonPatale=>之间的区别是什么?为什么案例e:NonFatal=>不起作用,但案例e:IOException=>起作用?说真的,这种语言并没有停止让我他妈的感到困惑,即使是在做了12年的程序员之后:DNonFatal不是一种例外。NonFatal是一个提取器,允许您捕获所有非致命异常。我在自己的文章中给出的答案更深入。
import scala.util.control.NonFatal
import scala.language.reflectiveCalls

type Resource = { def close(): Unit }

def using[A <: Resource, B](opener: String => A)(name: String)(func: A => B): Unit = {

  var resource = null.asInstanceOf[A]

  try {
     resource = opener(name)
     func(resource)
  } catch {
     case NonFatal(e) => println(s"Failed to open resource '${name}' (${e.getMessage})")
  } finally {
     println("Closing resource...")
     resource.close()
  }

}

final class SomeKindOfResource(n: String) {

  def use(): Int = n.toInt

  def close(): Unit = {}

}

using(new SomeKindOfResource(_))("42")(n => println(n.use()))
using(new SomeKindOfResource(_))("NaN")(n => println(n.use()))
var resource = null.asInstanceOf[A]