Scala (7): constructors, class and trait

Constructor

Constructor is not a special method, which we can use to initialize internal status. So constructor’s concept is very board in Scala. Primary constructors in Scala is the class’s body and it’s parameter list comes right after the class name.

class Calculator(brand: String) {
  /** 
   * a constructor
   */
  val color: String = if (brand == "TI") {
    "blue"
  } else if (brand == "HP") {
    "black"
  } else {
    "white"
  }
  // an instance method
  def add(m: Int, n: Int): Int = m + n
}

So now, we can use constructor to create an instance. The relationship between constructor, class and instance is very clear. constructor uses class to build abstract concept first, and then instance is to make this abstract concept concrete.

val calc = new Calculator("HP") // calc: Calculator = Calculator@1e64cc4d
calc.color // String = black

Auxiliary constructors

Auxiliary constructors are created by defining methods named “this”. In Scala the primary constructor defines all of the values that is required to create an instance of the class, all other constructors must also apply these values even if they don’t themselves require them as parameters.

class Greater(message: String, secondaryMessage: String) {
  def this(message: String) = this(message, "")
  def SayHi() = println(message + secondaryMessage)
}
val greater = new Greater("Hello world!")
greater.SayHi()

Abstract classes

Comparing to trait, abstract class allows constructor parameters. So use an abstract class whenever a base behavior must have constructor parameters. Abstract means you can’t create an instance of it. You need create another class to extend this abstract class to implement some methods.

abstract class Greeter(message: String) {
  def SayHi() = println(message)
}
class SwedishGreeter(message: String) extends Greeter(message: String) {
}
val swedishGreeter = new SwedishGreeter("hello world")
swedishGreeter.SayHi() // output: hello world

Another complex example:

abstract class BaseController(db: Database) {
  def save { db.save}
  def update { db.update }
  def delete { db.delete }

  // abstract
  def connect // subclass should implement this

  // an abstract method that returns a String
  def getStatus: String // subclass should implement this

  // an abstract method takes a parameter
  def setServerName(serverName: String) // subclass should implement this
}

When a class extends the BaseController class, it must implement the connect, getStatus, and setServerName methods, or be declared abstract.

Traits

Traits can be treated as the collection of fields and methods, which can be mixed with class.

trait Car {
  val brand: String
}
trait Shiny {
  val shineRefraction: Int
}
class BMW extends Car {
  val brand = "BMW"
}

One class can extend multi-traits by with.

class BMW extends Car with Shiny {
  val brand = "BMW"
  val shineRefraction = 12
}

Here is an example to use trait.

trait ForEachAble[A] {
  def iterator: java.util.Iterator[A]
  def foreach(f: A => Unit) = {
    val iter = iterator 
    while (iter.hasNext)
      f(iter.next)
  }
}

val list = new java.util.ArrayList[Int]() with ForEachAble[Int]
list.add(1); list.add(2)

println("For each: "); list.foreach(x => println(x))
// output:
// For each:
// 1 
// 2

Both trait and abstract can be inherited from class, and force the child to finish the definition of some behaviors. When you choosing between the two, you should consider two factors:

  • You should use trait as priority. One class can extend multi-traits, but only one abstract
  • If you want to build constructor parameter, you should use abstract. Because abstract class can accept parameter for the constructor, but trait can’t. For example, you can’t do like this: trait t(i: Int) {}, since parameter i is illegal.
Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s