Scala class extends {}

前端 未结 3 1127
盖世英雄少女心
盖世英雄少女心 2021-01-11 14:21

By chance I came across weird compiling Scala syntax:

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


        
相关标签:
3条回答
  • 2021-01-11 14:44

    This is actually a strange quirk in Scala's syntax. An extraneous extends is allowed before beginning the body of the class. Here are the relevant parts from the Scala Syntax Summary:

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

    ClassTemplateOpt is everything after the class's parameters, in this case everything from extends onwards. The usual use of extends is the first alternation of ClassTemplateOpt, with extends being followed either by a parent or an early initializer. However, an early initializer cannot contain a def, and there is no way to interpret the contents of the braces as a parent. It cannot be a structural type because hi has a concrete definition.

    The second alternation allows the class parameters to be immediately followed by the class body, without using extends. However, an optional extends is allowed. The extends in OP's code is an example of this, and is exactly equivalent to the same code without the optional extends:

    class Some {
      def hi = println("hi")
    }
    
    0 讨论(0)
  • 2021-01-11 14:48

    Yes this is Scala's structural typing or more commonly known as duck typing.

    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
    

    You can also declare your stuctural types with the "type" keyword.

    type Duck = { def quack(): String }
    
    def quackMyDuck(duck: Duck) {
        println(duck.quack())
    }
    
    0 讨论(0)
  • 2021-01-11 15:09

    This is actually just a syntactical accident (I think). Scala allows early definitions which look like

    class Some extends {
      ...
    } with ATrait
    

    so the parser also accepts class Some extends { ... } which is equivalent to class Some { ... } (source).

    0 讨论(0)
提交回复
热议问题