





















































In this article by Md. Rezaul Karim and Sridhar Alla, author of Scala and Spark for Big Data Analytics, we will discuss the basic object-oriented features in Scala. In a nutshell, the following topics will be covered in this article:
(For more resources related to this topic, see here.)
Before entering the depth of OOP features, at first, we need to know the details of the different types of variables and data types in Scala. To declare a variable in Scala, you need to use the var or val keywords. The formal syntax of declaring a variable in Scala is as follows:
val or var VariableName : DataType = Initial_Value
For example, let's see how we can declare two variables whose data types are explicitly specified as shown:
var myVar : Int = 50
val myVal : String = "Hello World! I've started learning Scala."
Even you can just declare a variable without specifying the data type. For example, let's see how to declare a variable using var or val:
var myVar = 50
val myVal = "Hello World! I've started learning Scala."
There are two types of variables in Scala--mutable and immutable--that can be defined as this:
In general, for declaring a mutable variable, the var keyword is used. On the other hand, the val keyword is used for specifying an immutable variable. To see an example of using the mutable and immutable variables, let's consider the following code segment:
package com.chapter3.OOP
object VariablesDemo {
def main(args: Array[String]) {
var myVar : Int = 50
valmyVal : String = "Hello World! I've started learning Scala."
myVar = 90
myVal = "Hello world!"
println(myVar)
println(myVal)
}
}
The preceding code works fine until myVar = 90, since myVar is a mutable variable. However, if you try to change the value of the immutable variable (that is, myVal), as shown earlier, your IDE will show a compilation error saying that reassignment to val as follows:
Don't worry looking at the preceding code with object and method! We will discuss classes, methods, and objects later in this article, then things will get clearer.
In Scala, variables can have three different scopes depending on the place where you have declared them:
As discussed earlier, object fields can be mutable or immutable (based on the declaration types, using either var or val). However, they can’t be both at the same time.
It is to be noted that method parameters/arguments are always immutable, no matter what is/are the keywords specified.
According to the earlier section, val is used to declare immutable variables, so can we change the values of these variables? Also, will it be similar to the final keyword in Java? To help us understand more about this, we will use this code snippet:
scala> var testVar = 10
testVar: Int = 10
scala> testVar = testVar + 10
testVar: Int = 20
scala> val testVal = 6
testVal: Int = 6
scala> testVal = testVal + 10
<console>:12: error: reassignment to val
testVal = testVal + 10
^
scala>
If you ran the preceding code, an error at compilation time will be noticed, which will tell that you are trying to reassign to a val variable. In general, mutable variables bring a performance advantage. The reason is that this is closer to how the computer behaves and introducing immutable values forces the computer to create a whole new instance of an object whenever a change (no matter how small) to that instance is required.
As mentioned Scala is a JVM language, so it shares lots of commonalities with Java. One of these commonalities is the data types; Scala shares the same data types with Java. In short, Scala has all the data types as Java, with the same memory footprint and precision. Objects are almost everywhere in Scala and all data types are objects; you can call methods in them, as illustrated:
Sr.No | Data type and description |
1 | Byte: An 8 bit signed value; range is from -128 to 127 |
2 | Short: A 16 bit signed value; range is -32768 to 32767 |
3 | Int: A 32 bit signed value; range is -2147483648 to 2147483647 |
4 | Long: A 64 bit signed value; range is from -9223372036854775808 to 9223372036854775807 |
5 | Float: A 32 bit IEEE 754 single-precision float |
6 | Double: A 64 bit IEEE 754 double-precision float |
7 | Char: A 16 bit unsigned Unicode character; ranges from U+0000 to U+FFFF |
8 | String: A sequence of Chars |
9 | Boolean: Either the literal true or the literal false |
10 | Unit: Corresponds to no value |
11 | Null: Null or empty reference |
12 | Nothing: The subtype of every other type; it includes no values |
13 | Any: The supertype of any type; any object is of the Any type |
14 | AnyRef: The supertype of any reference type |
All the data types listed in the preceding table are objects. However, note that there are no primitive types as in Java. This means that you can call methods on an Int, Long, and so on:
val myVal = 20
//use println method to print it to the console; you will also notice that if will be inferred as Int
println(myVal + 10)
val myVal = 40
println(myVal * "test")
Now you can start playing around with these variables. Now, let's get some ideas on how to initialize a variable and work on the type annotations.
In Scala, it's a good practice to initialize the variables once declared. However, it is to be noted that uninitialized variables aren’t necessarily nulls (consider types such as Int, Long, Double, and Char) and initialized variables aren't necessarily non-null (for example, val s: String = null). The actual reasons are the following:
Although Scala language requires that you initialize your instance variable before using it, Scala does not provide a default value for your variable. Instead, you have to set up its value manually using the wildcard underscore, which acts like a default value, as follows:
var name:String = _
Instead of using names such as val1, and val2, you can define your own names:
scala> val result = 6 * 5 + 8
result: Int = 38
You can even use these names in subsequent expressions, as follows:
scala> 0.5 * result
res0: Double = 19.0
If you used the val or var keyword to declare a variable, its data type will be inferred automatically according to the value that you assigned to this variable. You also have the luxury of explicitly stating the data type of the variable at declaration time:
val myVal : Integer = 10
Now, let's see some other aspects that will be needed while working with the variable and data types in Scala. We will see how to work with type ascription and lazy variables.
Type ascription is used to tell the compiler what types you expect out of an expression, from all possible valid types. Consequently, a type is valid if it respects the existing constraints, such as variance and type declarations; it is either one of the types the expression it applies to "is a" or there's a conversion that applies in scope. So technically, java.lang.String extends java.lang.Object; therefore, any String is also an Object. Consider the following example:
scala> val s = "Ahmed Shadman"
s: String = Ahmed Shadman
scala> val p = s:Object
p: Object = Ahmed Shadman
scala>
The main characteristic of a lazy val is that the bound expression is not evaluated immediately, but once on the first access. Here lies the main difference between val and lazy val. When the initial access happens, the expression is evaluated and the result bound to the identifier of the lazy val. On subsequent access, no further evaluation occurs; instead, the stored result is returned immediately. Let's look at an interesting example:
scala> lazy val num = 1 / 0
num: Int = <lazy>
If you see the preceding code in Scala REPL, you will note that the code runs very well without giving any error even though you divided an integer with 0! Let's look at a better example:
scala> val x = {println("x"); 20}
x
x: Int = 20
scala> x
res1: Int = 20
scala>
This works, and you can access the value of the x variable when required later on. These are just a few examples of using lazy val concepts. The interested readers should access https://blog.codecentric.de/en/2016/02/lazy-vals-scala-look-hood/ for more details.
The structure code in a sane way with classes and traits enhance the reusability of your code with generics and create a project with standard and widespread tools. Improve on the basics to know how Scala implements the OO paradigm to allow building modular software systems.