Max
Max

Reputation: 1877

Scala class extends {}

By chance I came across weird compiling Scala syntax:

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

Guys:

Thanks.

Upvotes: 13

Views: 1154

Answers (3)

wingedsubmariner
wingedsubmariner

Reputation: 13667

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")
}

Upvotes: 8

Alexey Romanov
Alexey Romanov

Reputation: 170899

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

Upvotes: 6

Karl
Karl

Reputation: 1230

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())
}

Upvotes: -1

Related Questions