13

By chance I came across weird compiling Scala syntax:

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

Guys:

  • Is it an official Scala supported syntax?
  • Does it mean simply extending the Object?
  • Does it somehow relate to "duck typing"?
  • Do you know interesting or tricky usages of this?

Thanks.

Max
  • 1,741
  • 3
  • 23
  • 40

3 Answers3

8

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")
}
wingedsubmariner
  • 13,350
  • 1
  • 27
  • 52
6

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

Community
  • 1
  • 1
Alexey Romanov
  • 167,066
  • 35
  • 309
  • 487
  • 2
    It appears pre-initialized/early definitions don't permit functions to be declared though. Doing the following won't compile: trait ATrait; class Some extends { def hi = println("hi")} with ATrait – Karl Jul 19 '14 at 16:43
-1

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())
}
Karl
  • 1,220
  • 9
  • 16