The with Keyword in Scala

Suraj P Jun 13, 2022
The with Keyword in Scala

This article will demonstrate how to use the with keyword in Scala.

Use the with Keyword in Scala

This keyword is usually used when dealing with class compositions with mixins. Mixins are traits that are used to compose a class.

This is somewhat similar to a Java class that can implement an interface.

Let’s see an example to understand the with keyword better:

abstract class vehicle {
  val message: String
}
class Car extends vehicle {
  val message = "I'm an instance of class vehicle"
}
trait sportsCar extends vehicle {
  def ourMessage = message.toUpperCase()
}
class temp extends Car with sportsCar

val obj = new temp
println(obj.message)  // I'm an instance of class vehicle
println(obj.ourMessage)  // I'M AN INSTANCE OF CLASS VEHICLE

In the above code, the class temp has superclass Car and mixin sportsCar. A class can extend only one superclass but many mixins using the with keyword; a superclass and mixins can have the same supertype.

Let’s look at another example. First, let us create an abstract class with a type T and some standard iterator methods.

abstract class ourIterator {
  type T
  def hasNext: Boolean
  def next(): T
}

Now, let’s create a concrete class where all the abstract members’ implementations of T, which are hasNext and next, are present.

class StringIterator(str: String) extends ourIterator {
  type T = Char
  private var i = 0
  def hasNext = i < str.length
  def next() =
  {
    val ch = str.charAt(i)
    i += 1
    ch
  }
}

Let’s create a trait that also extends the class ourIterator.

trait anotherIterator extends ourIterator {
  def foreach(X: T => Unit): Unit = while (hasNext) X(next())
}

The trait anotherIterator implements the foreach() method calling the function X: T => Unit continuously on the next element next() as long as there are more elements while(hasNext).

Since anotherIterator is a trait, it does not need to implement any abstract members of the ourIterator class. Now we can combine the functionalities of anotherIterator and StringIterator into a single class, as shown below:

class temp extends StringIterator("Tony") with anotherIterator
val obj = new temp
obj.foreach(println)

Full working code:

abstract class ourIterator {
  type T
  def hasNext: Boolean
  def next(): T
}

class StringIterator(str: String) extends ourIterator {
  type T = Char
  private var i = 0
  def hasNext = i < str.length
  def next() =
  {
    val ch = str.charAt(i)
    i += 1
    ch
  }
}

trait anotherIterator extends ourIterator {
  def foreach(X: T => Unit): Unit = while (hasNext) X(next())
}

class temp extends StringIterator("Tony") with anotherIterator
val obj = new temp
obj.foreach(println)

Output:

T
o
n
y

In the above code, the new class temp has StringIterator as a superclass and anotherIterator as a mixin. Just with single inheritance, achieving this level of flexibility will not be possible.

Author: Suraj P
Suraj P avatar Suraj P avatar

A technophile and a Big Data developer by passion. Loves developing advance C++ and Java applications in free time works as SME at Chegg where I help students with there doubts and assignments in the field of Computer Science.

LinkedIn GitHub