【问题标题】:Scala ActionListener / anonymous function type mismatchScala ActionListener / 匿名函数类型不匹配
【发布时间】:2010-07-13 16:15:01
【问题描述】:

尝试实现类似于 http://www.codecommit.com/blog/scala/scala-for-java-refugees-part-6 的高阶函数示例中的代码

val button = new JButton("test")
button.addActionListener{ e:ActionEvent => println("test") }
add(button)

导致以下内容

error: type mismatch;
found   : (java.awt.event.ActionEvent) => Unit 
required: java.awt.event.ActionListener
   button.addActionListener{ e:ActionEvent => println("test") }
                                           ^

至少对于我系统上的 Scala 编译器版本 2.7.6.final 来说是这样。我能够以 Java 风格的方式显式实现匿名 ActionListener 来实现我想要的。

button.addActionListener( new ActionListener() {
  def actionPerformed(e:ActionEvent) { println("test") }
})

据我了解,Scala 应该能够使用鸭子类型来使 ActionListener 的这种显式实现变得不必要;那么为什么它不在这里工作呢?在这一点上,我几乎没有鸭子打字的实际​​经验。

【问题讨论】:

    标签: scala type-conversion higher-order-functions


    【解决方案1】:

    Duck-typing 与您的代码不起作用的原因无关。这是 因为 Scala 的类型系统不提供接口类型之间的隐式转换 和默认的函数类型。但是,如果定义了以下隐式转换, 您的代码工作正常。

    implicit def toActionListener(f: ActionEvent => Unit) = new ActionListener {
      def actionPerformed(e: ActionEvent) { f(e) }
    }
    

    这种隐式转换提供从 (ActionEvent => Unit) 到 ActionListner 的转换。

    【讨论】:

    • 不像狂热分子,但值得注意的是,Groovy 和各种 Java 闭包提案都包含从适当的函数类型到单一方法接口的隐式转换。这对于 Runnable 或 Comparable 等接口非常方便。在 Scala 中,您要么需要手动执行此转换,要么依赖 pimped 库来执行此操作。
    • @Dave 是的...如果类型不匹配,则自动转换它。我认为 Scala 没有选择这种方式的原因应该很明显了。
    • 哦,当然。它只对 Groovy 和 Java 有意义,因为它们不包含任何扩展现有库的好方法,因此它们需要这种自动转换以使使用遗留 Java 变得不痛苦。 Scala 对遗留库有皮条客,应该(并且正在)编写新库以支持函数形式而不是单方法接口。
    【解决方案2】:

    Scala 不是鸭式的。它具有可选的显式结构类型,但这与您的代码无法正常工作的原因没有任何关系。

    您的代码不起作用,因为 JButton.addActionListener 需要 ActionListener 作为其参数,而不是函数。即使 scala 是鸭式的,你也不能只传递一个函数,因为 ActionListener 上可用的相同方法在函数上不可用。

    请注意,文章说“让我们假设我们可以重写 Swing 以充分利用 Scala 的语法”,也就是说,该文章并未声称向您展示了实际的有效代码。

    然而 scala 确实有它自己的 swing 包 (scala.swing),其中包含的类比它们的 java 等价物更“scalaish”。

    【讨论】:

    • 啊,文章中的那句话确实是中肯的。我有一种感觉,在公共场合提出问题必然会暴露我的一些基本阅读理解失败......不过,你的回答是有益的。谢谢。
    猜你喜欢
    • 1970-01-01
    • 2014-05-29
    • 2017-04-01
    • 2015-09-23
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多