dankilman
dankilman

Reputation: 886

What is the proper way of calling a superclass constructor in Scala?

Suppose I would like to extend class C, getting SubC.

Now I would like to access the variable c in SubC as presented in the example below in the method printC.

The following does not work, as calling printC on a SubC instance will print SubC's c and not C's c (I guess I could have picked better names...)

class C(protected var c : Int) {
  def update(n : Int) {
    c = n
  }
}

class SubC(c: Int) extends C(c) {
  def printC : Unit = {
    println(c)
  }
}

object Main {
  def main(args: Array[String]) {
    val subC = new SubC(1)
    subC.update(3)
    subC.printC // prints 1
  }
}

A possible (but undesirable) solution would be:

class SubC(cc: Int) extends C(cc) {
  def printC = {
    println(c)
  }
}

This works but it introduces a new (and unneeded) identifier cc into scope.

Is there a better (cleaner) way of doing this?

PS: To put the example above into some context. What I actually want to do is to augment C with some traits without introducing new identifiers into scope.

Upvotes: 2

Views: 262

Answers (2)

Daniel C. Sobral
Daniel C. Sobral

Reputation: 297185

Use self types:

class SubC(c: Int) extends C(c) {  
  self: C =>
  def printC : Unit = {            
    println(self.c)              
  }
}

Upvotes: 2

Mitch Blevins
Mitch Blevins

Reputation: 13196

This is probably the best way to augment C with traits without introducing new identifiers in scope:

class C(protected var c : Int) {
  def update(n : Int) {
    c = n
  }
}

trait CanPrintC {
  self: C =>
  def printC : Unit = {
      println(c)
  }
}
class SubC(c: Int) extends C(c) with CanPrintC 

object Main {
  def main(args: Array[String]) {
    val subC = new SubC(1)
    subC.update(3)
    subC.printC // prints 3
  }
}

Upvotes: 9

Related Questions