【问题标题】:Scala class extends {}Scala 类扩展 {}
【发布时间】:2014-07-20 21:27:54
【问题描述】:

我偶然发现了奇怪的 Scala 编译语法:

class Some extends {
  def hi = println("hi")
}

伙计们:

  • 它是 Scala 官方支持的语法吗?
  • 这是否意味着简单地扩展Object
  • 它是否与“鸭子打字”有关?
  • 你知道这个有趣或棘手的用法吗?

谢谢。

【问题讨论】:

    标签: scala types


    【解决方案1】:

    这实际上是 Scala 语法中的一个奇怪的怪癖。在开始类的主体之前允许使用无关的extends。以下是来自Scala Syntax Summary的相关部分:

    ClassDef          ::=  id [TypeParamClause] {ConstrAnnotation} [AccessModifier] 
                           ClassParamClauses ClassTemplateOpt 
    ClassTemplateOpt  ::=  ‘extends’ ClassTemplate | [[‘extends’] TemplateBody]
    ClassTemplate     ::=  [EarlyDefs] ClassParents [TemplateBody]
    

    ClassTemplateOpt 是类参数之后的所有内容,在本例中是从extends 开始的所有内容。 extends 的常用用法是ClassTemplateOpt 的第一个交替,extends 后面跟着一个父或早期初始化程序。但是,早期初始化程序不能包含def,并且无法将大括号的内容解释为父项。它不能是结构类型,因为hi 有一个具体的定义。

    第二个替换允许类参数紧跟在类主体之后,而不使用extends。但是,允许使用可选的extends。 OP 代码中的extends 就是一个例子,它完全等同于没有可选扩展的相同代码:

    class Some {
      def hi = println("hi")
    }
    

    【讨论】:

      【解决方案2】:

      这实际上只是一个语法意外(我认为)。 Scala 允许 early definitions 看起来像

      class Some extends {
        ...
      } with ATrait
      

      所以解析器也接受class Some extends { ... },相当于class Some { ... }(source)

      【讨论】:

      • 看来预初始化/早期定义不允许声明函数。执行以下操作不会编译: trait ATrait;类 Some 使用 ATrait 扩展 { def hi = println("hi")}
      【解决方案3】:

      是的,这是 Scala 的结构类型或更常见的鸭子类型。

      object LoudDuck {
          def quack(): String = "QUACK"
      }
      
      object QuietDuck {
          def quack(): String = "quack"
      }
      
      object CowDuck {
          def quack(): String = "moo"
      }
      
      def quackMyDuck(duck: { def quack(): String }) {
          println(duck.quack())
      }
      
      scala>quackMyDuck(LoudDuck)
      QUACK
      
      scala>
      
      scala>quackMyDuck(QuietDuck)
      quack
      
      scala>
      
      scala>quackMyDuck(CowDuck)
      moo
      

      您还可以使用“type”关键字声明您的结构类型。

      type Duck = { def quack(): String }
      
      def quackMyDuck(duck: Duck) {
          println(duck.quack())
      }
      

      【讨论】:

      • 你给出的例子结构类型,但有问题的不是。
      • 考虑type T = { def hi = println("hi") } - 它不能编译,因为结构类型不能有定义。
      猜你喜欢
      • 1970-01-01
      • 2019-08-31
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多