Scala Interview Questions and Answers

Scala is a strong statistically typed general-purpose programming language that supports functional programming as well as object-oriented programming. Most of the design decisions of Scala are aimed at addressing criticisms of Java. Whether you are a beginner or an intermediate or an expert Scala professional, this write-up will help you boost your confidence and learning of Scala. The questions focus on various components of Scala namely, Service components, Pesistence and Cluster components, Broker API components and more. This guide brings you step-by-step explanations for every questions that will help you understand the conception in detail. With the below Scala interview questions, you can be confident about your preparation for the upcoming interview.

  • 4.5 Rating
  • 19 Question(s)
  • 32 Mins of Read
  • 4481 Reader(s)

Beginner

Scala is a general-purpose language that runs on JVM. It has some unique features which make it very useful for developing programs of different shapes and sizes. Starting from a small script to enterprise-level multi-module applications, Scala gives developers a lot of flexibility in design and implementation. 

Inferring types, implicit conversions, and conciseness help define custom control structures and domain-specific languages. On one side, its object-oriented features help to design systems with complex entities. On the other hand, the functional programming constructs help to develop bug-free and reusable code. In short, the language fits in serving all kinds of requirements. That’s why it is called a scalable language.

This is a frequently asked question in Scala interviews. 

In Scala, functions can be written as literals. They can be assigned to any variable, can be passed to another function as an argument or can be returned from a function as a value. These functions are called first-order functions. For example, in the following code snippet, x => x*x is a first-order function which has been assigned to a value named square.

val square = x => x*x

A function that takes another function as an argument or returns a function is called a higher-order function. For example, the sumApplied() function as defined below is a higher-order function.

def sumApplied(x:Int, y:Int, f:Int => Int):Int = f(x) + f(y)

Scala has a feature to define a function in the body of another function. The scope of these functions is the declaring function only. That is, they are not accessible from anywhere else in the code. These functions are called local functions.

Sometimes we need a set of small functions to define a complete functionality. Those functions are not contextual in other places. In that scenario, local functions come into the picture. Let’s take an example.

object GCD {

def gcdList(list:List[Int]):Int = {

Local function

def gcd(x:Int, y:Int):Int =

if (y == 0) x else gcd(y, x%y)

list match {

case Nil => 0

case h::t => gcd(h, gcdList(t))

}

}

Here, the recursive function gcd() inside gcdList() is a local function.

Expect to come across this popular question in Spark Scala interviews.

In Scala, val and lazy val both are used to declare a value. When we declare a val and assign some expression in it, the expression is evaluated and assigned in that place. Whereas, for lazy val, the expression is evaluated and the value is assigned at the time of its first use.

Lazy vals are useful when object creation or expression evaluation is costly in terms of CPU and memory and the value may or may not be used based on some condition.

Function and method both terms are used when a code block takes a set of parameters and computes a value or performs some action based on the inputs. Such a block is called a function when it is not associated with any class. On the other hand, one such block is called a method when it is a member of a class.

For example, in the code below, getSalary() is a method of the class Employee, but sortBySalaryis function.

class Employee(val id:Long, val name:String, val salary:Int) {

//other members

def getSalary() = salary

}

Val employees: List[Employee] = … // fetch employees sortBySalary(employees)

A must-know for anyone heading into a Scala interview, this question is frequently asked in Scala coding interview questions.  

In Scala, while declaring a class, sometimes we specify some parameters which are mandatory to pass while instantiating an object of that type. These parameters are called class parameters.

As the body of the class plays the role of the primary constructor in Scala, these parameters actually define its arguments. If we declare the parameters with val or var, they become a member of the class. In the example below, id, name, and salary are the class parameters for the Employee class. Here, id and name are the members of the class, but the salary is not.

class Employee(val id:Long, val name:String, salary:Int)

Scala permits defining the auxiliary constructors of a class using this keyword. If we define one or more than one methods in the class body, they become the auxiliary constructors. The first statement of an auxiliary constructor must be either a call to the primary constructor or any other auxiliary constructor. For example,

class Customer(val id:Int, val name:String, val age:Int) { def this(id:Int, name:String, dob:LocalDate) = {

this(id, name,

Period.between(dob, LocalDate.now).getYears)

}

}

It's no surprise that this one pops up often in Scala interview questions for Spark.  

Scala doesn’t have a static keyword to define the object-independent methods. We can directly define them in a singleton object. Otherwise, we can use a companion object for a given class to hold those methods. For example, we can create a List in Scala in the following way,

val l = List(1, 2, 3, 4)

This is possible as there is a method named apply defined in the object - List .

A trait is like a Java interface declaring a set of methods and fields. The difference is that the members of a trait may not be abstract. If a class extends a trait, it should implement the abstract methods and fields declared by the trait. On the other hand, it may or may not override those methods having bodies. For example,

trait Comparable[T] {

def compare(other: T): Int;

def greaterThan (other: T) = compare(other) > 0

def lessThan (other: T) = compare(other) < 0

def isEqualTo (other: T) = compare(other) == 0

}

trait Loggable {

def log(out:PrintWriter)

}


Traits help us to build rich interfaces where a number of methods define their body in terms of a few abstract methods. This is useful when we intend to extend the functionalities of a trait without breaking the client code.

Traits are also very useful in mixing features in a type. A class can extend multiple traits. Moreover, one instance of a class can be created mixing in a number of traits inline as in:

class A(val x:Int)

val a = new A(10) with Comparable[A] with Loggable { override def compare(other: A):Int = this.x - other.x override def log(o: PrintWriter):Unit =

o.print(this.toString)

}


These features provide with a lot of flexibility to play with object creation with different attributes and behavior.

Advanced

A common question in Scala interview questions for experienced, don't miss this one.  

Immutability is a very important concept in software development. Immutable objects don’t change their state after construction. So they are very safe to use as a shared object in a multi-threaded environment. They also reduce the parts of code which need explicit synchronization and locks. 

This improves the overall performance of the system. Immutable objects help in writing pure functions or methods. There are no side effects in pure functions. That is why they make the whole application less bug-prone and easily testable.

A function is called pure if it doesn’t have any side effect (including I/O) in its execution. The computation result of a pure function only depends on its input values and programming logic, not anything else. That’s why for a specific set of input, the output is always the same in any environment.

A pure function is less bug-prone and easily testable. Also, we can cache the results of a pure function for particular inputs and thus can improve performance.

One of the most frequently posed Scala programming interview questions, be ready for it.  

Scala allows passing a block of code in a function which is evaluated only when it is used. This kind of parameter is called a by-name parameter. By-name parameters are often used while defining a new control structure. Let’s take an example.

def executionTime(f: => Any) = {
val start = System.currentTimeMillis() f

System.currentTimeMillis() - start

}

val t = executionTime { gcdList(List(18, 24, 36))

}

Scala defines 3 types of access modifiers:
Default: This is equivalent to the publicin Java, i.e., accessible from anywhere.
Protected: This makes members accessible in class, companion classes, and subclasses. However, one can mention the scope within which it can be accessible.
Private: The members with this access are available only in the same class and in the companion class - not in a subclass.

We can take an example to understand the scope of private and protected: 

package amt {
class A(protected[amt] val a:Int, private[this] val b:Int) package amt.sub1 {

class B {

val x = new A(10, 20) val p = x.a

val q = x.b // error: not accessible

}

}

}


In the above code, as the protected scope is bound inside package amt, the variable is accessible inside B. On the other hand, the scope of private is mentioned like this, that’s why it is not accessible outside its instance.

A staple in Scala scenario based coding interview questions, be prepared to answer this one.  

Scala import provides a number of flexibilities. We can exclude certain classes while importing the whole package:

import com.xyz.abc.{Abc => _, _} // excluding the class Abc

Also, it’s possible while importing that we can rename the existing classes. 

import com.xyz.abc.{Abc => Pqr, _} // renaming the class Abc

In Scala, every package permits one package object to declare. It is a singleton object where the defined members can be imported in a class through the package import. It lets the developer define top-level functions. Please note that overloading is not allowed in package objects. Let’s see an example:

package object myconverters {

def fromAtoB (a:A): B = ... //conversion logic def fromAToInt (a:A):Int = ... //conversion logic

different other converters

}

A statement is an instruction that performs some operation, whereas, an expression evaluates a value. In Scala, the basic control structures such as if and for-loop are expressions, as they return value and it can be assigned to a variable. For example, 

val isOdd = if (num%2 != 0) true else false

This question is a regular feature in Scala interview coding questions, be ready to tackle it.  

When a class extends multiple traits, it might happen that they have a common method. Now when that method is executed, it is very important to know the trait on which the method is invoked first. The linearization rule says that the common method execution would start in the traits from right to left as it is mentioned in the extended list.

Even if the traits have a common super trait or abstract class, the execution order would be linear so that no conflicts arise. Let’s take an example:

abstract class A {

def stringValue = "A "

}

trait AT extends A {

override def stringValue = "AT " + super.stringValue

}

trait BT extends A {

override def stringValue = "BT " + super.stringValue

}

trait CT extends BT with AT {

override def stringValue = "CT " + super.stringValue

}

class D extends CT {

override def stringValue = "D " + super.stringValue

}

/* The class hierarchy:

A

\

\ /

CT

|

D

*/

println(new D().stringValue)

Though the class hierarchy is like a graph, the execution of the method stringValue follows a particular order based on the linearization rule:

D CT AT BT A

This implies that if a class or trait extends multiple traits, such a common method execution starts from the extreme right in the extends list. That’s why stringValue of AT was executed before that of BT.

Scala automatically generates getter-setter methods for each field defined in a class after compilation. If there is a field as,

value:Int

the getter-setter methods for this field would be, 

def value:Int = this.value // Getter

def value_= (value:Int) = this.value = value // Setter


These methods are public for a public field whereas those are private for a private one.

However, the developer may create such public methods for a private field.

Also, they may declare getter-setter of a different pattern, like getXXX and setXXX .

Description

Scala is a high-level, general-purpose programming language designed by Martin Ordersky. It has some features of functional programming. Scala is becoming more renowned among Big data professionals. “Scala is hard to master though it is a very popular programming language”, this is true to some extent. But learning Scala can be easy with Scala training.

If you are preparing for a Scala job interview, you need to prepare for the essential interview questions for Scala. Although there is no one best approach here, the following Scala interview questions and answers will guide you in a whole new way. Given below is the list of the latest Scala programming interview questions and answers that are asked frequently in the interviews. 

These interview questions on Scala are divided into two parts:

  1. Interview questions and answers for freshers or Basic questions
  2. Interview questions and answers for experienced

So, get ready to face the interviews with these top Scala interview questions and answers.

Read More
Levels