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



下面的例子,尤其是这个代码:

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 => { .....

我想扩展using方法,以便它接收一个字符串(文件名(、一个打开源代码的函数和处理函数,而不是实现close的类型。通过这种方式,我将避免在给定文件不存在的情况下在上面的示例中抛出的异常。

所以我得到了这个代码:

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块之外声明resource变量(因此我可以在finally块中访问它(。如果我只是像var resource:A = opener(name)一样把它放在try块中,它将工作,但我无法在finally块中达到resource

我该如何解决?我不得不说,我还是Scala的初学者,所以我有点迷失在这里。

这里有一个修改后的示例,您也可以在Scastie:上运行

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]

请注意,不管你怎么想,这不会抛出NullPointerException。你可以在这里阅读更多关于它的信息。

我添加了一些你可能感兴趣的东西:

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

  • { def close(): Unit }命名为使其在使用type的方法签名中可读性更强的内容

  • 使用NonFatal处理异常(您可以在此处阅读更多信息(

最新更新