Function and Data
In this article, we will explain how functions create and encapsulate data.
Class
In Scala, we create a data structure using class.
Data Abstraction
The ability to choose different implementations of the data without affecting clients is data abstraction.
For example, we have 3 ways to implement numer
and denom
of the class Rational
.
class Rational(var x: Int, var y: Int) {
private def gcd(a: Int, b: Int): Int = {
if (b == 0) a
else gcd(b, a % b)
}
// implemention 1: run gcd whenever numer or denom is called.
def numer = x / gcd(x, y)
def numer = y / gcd(x, y)
}
class Rational(var x: Int, var y: Int) {
private def gcd(a: Int, b: Int): Int = {
if (b == 0) a
else gcd(b, a % b)
}
// implemention 2: run gcd only one time when the instance of the class is created
private val g = gcd(x, y)
def numer = x / g
def denom = y / g
}
class Rational(var x: Int, var y: Int) {
private def gcd(a: Int, b: Int): Int = {
if (b == 0) a
else gcd(b, a % b)
}
// implemention 3: run gcd only one time when the instance of the class is created, and get the numer's and demon's value
private val g = gcd(x, y)
val numer = x / g
val denom = y / g
}
Self reference
this
is the self reference using in a class. It references to the class's attributes and methods.
Precondition vs Assert
-
Precondition enforce the condition on the caller of the function. We use
require()
in Scala.class Rational(var x: Int, var y: Int) { require(y > 0, "Denominator must be positive.") }
-
Assert is used to check the codes.
val x = sqrt(y) assert(x >= 0)
Constructor
Primary constructor
It's in the definition of the class.
class Rational(var x: Int, var y: Int) {}
- It takes all the parameters.
- It runs all the statements in the class body.
Auxiliary constructors
The other constructors besides the primary one.
It's defined by this()
.
class Rational(var x: Int, var y: Int) {
def this(x: Int) = {
this(x, 1)
}
}