我正在阅读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()
答案 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,因此可能会花费很多。