【问题标题】:Hook pattern in ScalaScala 中的钩子模式
【发布时间】:2011-03-09 07:00:46
【问题描述】:

我正在寻找 Scala 中所有钩子的简明文档。钩子是程序流中可以拦截常见行为的任何情况。此类情况包括:

  • 类或特征的声明
  • 访问方法和字段
  • 混合线程、继承

我来自 Ruby 背景,例如,method_missing 允许拦截不存在的方法调用。

Scala 中是否提供这样的钩子?

马蒂亚斯

【问题讨论】:

标签: scala


【解决方案1】:

在 Scala 2.8 或更早版本中没有等效的 method_missing。在 Scala 2.9(正在开发中)中,将添加一个 Dynamic trait。对声明动态特征的对象的未知方法调用将由编译器自动转换为调用invokeDynamic。这个想法是以安全和理智的方式获得动态类型语言的一些功能,而不需要在不需要时支付动态类型的性能开销。当从 Scala 中调用以动态语言定义的对象时,它还简化了互操作性问题。

除此之外,在 Scala 中挂钩新行为主要是通过经典继承或通过隐式转换向对象添加新功能来完成的。

【讨论】:

    【解决方案2】:

    不,他们不是。在静态语言中,面向方面的编程可以用于某些相同的目的。见Can I do Aspect Oriented Programming in Scala? 但当然,“类或特征的声明”和“线程的混合、继承”不是控制流的一部分。如果你想拦截它们,你需要一个编译器插件。

    【讨论】:

      【解决方案3】:

      Scala 倾向于鼓励使用闭包,而不是您所说的钩子类型(由于静态类型和编译,大多数钩子无法方便地实现)。

      这需要您提前知道哪些地方可能需要通用行为的灵活性,但它非常强大且在可用时易于使用。例如,假设您有一个打印出人名的方法:

      case class Name(first: String, last: String) {
        def title = last + ", " + first(0).toUpper + "."
      }
      trait Familiar extends Name {
        override def title = first + " " + last(0).toUpper + "."
      }
      
      def listing(names: Array[Name]) = names.foreach(name => println(name.title))
      
      val jd1 = new Name("John","Doe)
      listing(Array(jd1))  // Prints Doe, J.
      val jd2 = new Name("John","Doe") with Familiar
      listing(Array(jd2))   // Prints John D.
      

      但是,如果您真的要大量更改名称打印,则最好将其构建在:

      case class Name(first: String, last: String) {
        def title = last + ", " + first(0).toUpper + "."
      }
      
      def listing(names: Array[Name], address: Name => String = _.title) = 
        names.map(address).foreach(println)
      
      val jd = new Name("John", "Doe")
      listing(Array(jd))  // Uses default, so prints Doe, J.
      listing(Array(jd), n => n.first + " " + n.last(0).toUpper + ".")  // Prints John D.
      

      【讨论】:

        【解决方案4】:

        Scala 中没有这样的东西。

        或者,更准确地说,静态类型确保我们知道在编译代码时会发生什么。任何这样的钩子都会改变运行时的行为,这会破坏静态类型的目的。

        可以通过编译器插件在编译时修改行为,甚至可以通过类加载器在类加载时更改内容。

        【讨论】:

          猜你喜欢
          • 2016-06-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          • 2014-01-12
          • 2012-10-31
          • 2011-08-25
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多