我当时正在读Dubochet和Odersky的编译JVM上的结构类型 (好的,略读),我对下面的说法感到困惑:
生成技术创建Java接口来代表JVM上的结构类型。这些技术的复杂性在于,所有要作为程序中任何地方的结构类型使用的类都必须实现正确的接口。如果在编译时完成此操作,则会防止单独编译。
(强调后加)
考虑一下本文中的自动关闭示例:
type Closeable = Any { def close(): Unit }
def autoclose(t: Closeable)(run: Closeable => Unit): Unit = {
try { run(t) }
finally { t.close }
}我们不能为Closeable类型生成如下接口:
public interface AnonymousInterface1 {
public void close();
}并将autoclose的定义转换为
// UPDATE: using a view bound here, so implicit conversion is applied on-demand
def autoclose[T <% AnonymousInterface1](t: T)(run: T => Unit): Unit = {
try { run(t) }
finally { t.close }
}然后考虑一下autoclose的呼叫站点。
val fis = new FileInputStream(new File("f.txt"))
autoclose(fis) { ... }由于fis是一个不实现AnonymousInterface1的FileInputStream,所以我们需要生成一个包装器:
class FileInputStreamAnonymousInterface1Proxy(val self: FileInputStream)
extends AnonymousInterface1 {
def close() = self.close();
}
object FileInputStreamAnonymousInterface1Proxy {
implicit def fis2proxy(fis: FileInputStream): FileInputStreamAnonymousInterface1Proxy =
new FileInputStreamAnonymousInterface1Proxy(fis)
}我一定是错过了什么,但我不清楚是什么。为什么这种方法会阻止单独的汇编?
发布于 2010-08-29 00:39:20
我实际上使用了您在Scala ARM库中描述的隐式方法(使用类型)。请记住,这是一个手工编码的问题解决方案。
这里最大的问题是隐含的决议。编译器不会动态地为您生成包装器,您必须提前完成,并确保它们是隐式作用域之一。这意味着(对于Scala),我们为任何资源提供“公共”包装,当我们找不到合适的包装时,我们又回到了基于反射的类型。这使用户可以使用正常的隐式规则指定自己的包装器。
参见:资源类型特征及其所有预定义包装器。
此外,我在博客中更详细地描述了隐式分辨率魔术:猴子打补丁、鸭子打字和类型类。
在任何情况下,每次使用结构类型时,您可能都不想手动编码类型类。如果您实际上希望编译器自动创建一个界面并为您执行魔术,那么它可能会变得很混乱。每次定义结构类型时,编译器都必须为其创建一个接口(可能在某个地方?)。我们现在需要为这些东西添加名称空间。此外,每次调用时,编译器都必须生成某种包装器实现类(同样带有名称空间问题)。最后,如果我们有两个不同的方法,具有相同的结构类型,分别编译,我们刚刚爆炸了我们需要的接口数量。
这并不是说这个障碍是无法克服的,但是如果你想要对特定类型进行“直接”访问的结构类型,那么类型特征模式似乎是你今天的最佳选择。
发布于 2010-08-17 03:37:07
正如我从讨论的Scala-Inernals邮件列表中回忆起来的那样,这个问题是对象标识(由当前编译方法保留的)在包装值时丢失的。
发布于 2010-08-17 16:17:08
想想看。考虑A类
class A { def a1(i: Int): String = { ... }; def a2(s: String): Boolean = { ... }在程序中的某个位置,可能在单独编译的库中,使用这种结构类型:
{ def a1(i: Int): String }在其他地方,这个被使用:
{ def a2(s: String): Boolean }除了全局分析之外,A类是如何用必要的接口来修饰的,以便能够在那些遥远的结构类型被指定的地方使用?
如果使用给定类所遵循的每一种可能的结构类型来生成捕获该结构类型的接口,那么这种接口就会爆炸。请记住,结构类型可能会提到多个必需成员,因此对于具有N个公共元素(vals或defs)的类来说,这些N的所有可能子集都是必需的,这就是基数为2^N的N的powerset。
https://stackoverflow.com/questions/3498954
复制相似问题