在Scala中

时间:2016-07-08 08:12:05

标签: scala functional-programming

我正在阅读Martin Odersky关于Scala类型系统的采访,并且已经说了以下内容

  

Scala比Java更具表现力的一个方面是它可以让你表达这些东西。在Scala中,可以有一个类型:使用close方法不带参数并返回Unit(类似于Java中的void)。您还可以将其与其他约束结合使用。你可以说:从特定类继承的任何东西,除了这些特殊方法都带有这些签名。或者你可以说:从这个类继承的东西,它有一个特定类型的内部类。从本质上讲,您可以通过说明类型中需要的内容来对结构类型进行表征,以便您可以使用它们。

有人可以在Scala中编写一个片段来展示我如何在结构上表征类型?阅读后我觉得我应该能够做到以下几点:

type CanClose { def close: Unit }
val closeableFile: CanClose = new File()
val closeableStream: CanClose = new Stream()

2 个答案:

答案 0 :(得分:4)

在Scala中,可以通过其结构来识别类型,从而实现它通常被称为鸭子类型的类型。

这是一个例子

scala> def close(x: { def close: Unit }): Unit = x.close
warning: there was one feature warning; re-run with -feature for details
close: (x: AnyRef{def close: Unit})Unit

scala> class CanBeClosed {
     |   def close: Unit = println("I'm closed now")
     | }
defined class CanBeClosed

scala> class CannotBeClosed {
     | }
defined class CannotBeClosed

scala> close(new CanBeClosed)
I'm closed now

scala> close(new CannotBeClosed)
<console>:13: error: type mismatch;
 found   : CannotBeClosed
 required: AnyRef{def close: Unit}
       close(new CannotBeClosed)

但是,重要的是要注意结构类型是使用运行时反射实现的,因此它会对性能产生影响。

这就是为什么你在第一个定义上收到警告的原因(你可以通过导入import scala.language.reflectiveCalls来使警告静音)

答案 1 :(得分:1)

马丁正在谈论Structural Types。这意味着你可以做到:

java.io.File

我们只定义了结构我们期望该类型的行为,我们并不需要实际继承任何通用接口,如Java所要求的。

在您的示例中,close()没有实现Firebug方法,因此不会起作用,但是遵守该方法签名的任何其他类型都会有效。需要注意的一件重要事情是,在引擎盖下,这需要Scala遵从reflection,因此可能会花费很多。