代码之家  ›  专栏  ›  技术社区  ›  Aaron Novstrup

为什么结构类型的编译时生成技术会阻止单独编译?

  •  3
  • Aaron Novstrup  · 技术社区  · 15 年前

    我在读杜博切特和奥德斯基的书 Compiling Structural Types on the 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 }
    }
    

    然后考虑一个呼叫站点 自动关闭 :

    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)
    }
    

    某物 ,但我不清楚是什么。为什么这种方法会阻止单独编译?

    3 回复  |  直到 15 年前
        1
  •  1
  •   jsuereth    15 年前

    我实际上使用了您在 Scala ARM library . 请记住,这是一个手工编码的解决方案的问题。

    这里最大的问题是隐含的解决方案。编译器不会动态地为您生成包装器,您必须提前生成包装器,并确保它们是隐式作用域中的一个。这意味着(对于Scala-ARM)我们可以为任何资源提供“公共”包装器,当我们找不到合适的包装器时,就返回到基于反射的类型。这样做的好处是允许用户使用普通的隐式规则指定自己的包装器。

    The Resource Type-trait 所有这些都是预定义的包装。

    Monkey Patching, Duck Typing and Type Classes .

    在任何情况下,您可能都不希望每次使用结构类型时都手工编码类型类。如果你真的想让编译器自动创建一个接口并为你施展魔法,它可能会变得一团糟。每次定义一个结构类型时,编译器都必须为它创建一个接口(可能是以太中的某个地方?)。我们现在需要为这些东西添加名称空间。而且,每次调用编译器都必须生成某种包装器实现类(同样还有名称空间问题)。最后,如果有两个具有相同结构类型的不同方法分别编译,那么我们只需分解所需的接口数。

    并不是说这个障碍无法克服,但是如果你想用“直接”访问特定类型的结构类型,那么类型特征模式似乎是你今天的最佳选择。

        2
  •  7
  •   Randall Schulz    15 年前

    a discussion Scala-Inernals 邮件列表的问题是,当前编译方法保留的对象标识在包装值时丢失。

        3
  •  4
  •   Randall Schulz    15 年前

    好好想想。考虑A级

    class A { def a1(i: Int): String = { ... }; def a2(s: String): Boolean = { ... }
    

    在程序的某些地方,可能在单独编译的库中,使用这种结构类型:

    { def a1(i: Int): String }
    

    { def a2(s: String): Boolean }
    

    除了全局分析之外,类A如何被必要的接口修饰,以允许它在指定那些遥远的结构类型的地方使用?

    推荐文章