Generative techniques create Java interfaces to stand in
for structural types on the JVM. The complexity of such
techniques lies in that all classes that are to be used as
structural types anywhere in the program must implement
the right interfaces. When this is done at compile time,it
prevents separate compilation.
(重点补充)
考虑论文中的autoclose示例:
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是FileInputStream,它没有实现AnonymousInterface1,我们需要生成一个包装器:
class FileInputStreamAnonymousInterface1Proxy(val self: FileInputStream) extends AnonymousInterface1 { def close() = self.close(); } object FileInputStreamAnonymousInterface1Proxy { implicit def fis2proxy(fis: FileInputStream): FileInputStreamAnonymousInterface1Proxy = new FileInputStreamAnonymousInterface1Proxy(fis) }
我必须遗漏一些东西,但我不清楚它是什么.为什么这种方法会阻止单独编译?
解决方法
这里最大的问题是隐式解决方案.编译器不会为您动态生成包装器,您必须提前生成包装器并确保它们是隐式范围.这意味着(对于Scala-ARM)我们为任何资源提供“通用”包装器,并在找不到合适的包装器时回退到基于反射的类型.这提供了允许用户使用常规隐式规则指定自己的包装器的优点.
请参阅:The Resource Type-trait及其所有预定义的包装器.
此外,我在博客中详细介绍了这种隐含分辨率魔法的技术:Monkey Patching,Duck Typing and Type Classes.
在任何情况下,您可能不希望每次使用结构类型时手动编码类型类.如果你真的希望编译器自动创建一个界面并为你做一些魔术,它可能会变得混乱.每次定义结构类型时,编译器都必须为它创建一个接口(也许在以太的某个地方?).我们现在需要为这些东西添加名称空间.此外,每次调用时,编译器都必须生成某种类型的包装器实现类(同样具有命名空间问题).最后,如果我们有两种不同的方法,它们具有相同的结构类型,我们只是分解了我们需要的接口数量.
并不是说障碍无法克服,但如果你想对特定类型进行“直接”访问的结构类型,那么类型 – 特征模式似乎是你今天最好的选择.
版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。