Object-Oriented Programming in Scala PDF
Document Details
Uploaded by ObtainableHyperbolic
Freie Universität Berlin
Tags
Related
- Object-Oriented Programming, Lecture 06 PDF
- Object Oriented Programming, Lecture 06.pdf
- Object Oriented Programming, Lecture 07.pdf
- Object Oriented Programming, Lecture 07.pdf
- An Introduction to Programming Through C++ Lecture 24 Revision PDF
- Object-Oriented Programming - Subtype Polymorphism Lecture Notes PDF
Summary
This document provides a tutorial on object-oriented programming concepts specifically in Scala. It introduces imperative programming constructs such as variables, while loops, do-while loops, and for loops. It explains how these concepts translate to object-oriented program practices in Scala.
Full Transcript
## Object-Oriented Programming in Scala ### Imperative Programming in Scala * **Variables:** In a purely functional context we do not allow the signal word *`var`*. This means when we want to go back to imperative programming (and going towards object-oriented programming) we need to use the *...
## Object-Oriented Programming in Scala ### Imperative Programming in Scala * **Variables:** In a purely functional context we do not allow the signal word *`var`*. This means when we want to go back to imperative programming (and going towards object-oriented programming) we need to use the *`var`* keyword so we can reassign objects to a variable. ```scala var i: Int = 0 i = i + 1 // reassignment of i println(i) // --> 1 ``` The syntax is similar to the *`val`* keyword, although it allows for modification. The reassignment does not mean we are changing an existing object, it is simply assigning a different object to the variable. We will see an example of how to change an existing object later when we look at arrays. The keyword for this is called a _mutable object_. * **While Loops:** The syntax for a while-loop in Scala looks as follows: ```scala while predicate do block ``` **Example:** Below prints the numbers 1 to 10 to the console. ```scala var i: Int = 1 while i <= 10 do println(i) i = i + 1 ``` * **Do While Loops:** In Scala, the predicate for a _do-while-loop_ is evaluated after the loop block has been executed for the first time. ```scala while block do predicate ``` * **For Loops:** The syntax for a _for-loop_ in Scala is as follows: ```scala for variable < collection do block ``` The *`variable`* is the name of the loop variable. The *`collection`* is a collection that will be iterated over, in this case, we'll use a range of numbers. You can also use a collection like a *`List`* or *`Array`* for this. **Example:** Iterating over a range of numbers from 1 to 10, including both 1 and 10. ```scala for i < 1 to 10 do println(i) ``` There are additional syntax elements you can use for your _for-loops_, like step size, counting backwards, or defining additional conditions for loop-elements. You can look at the Scala documentation for more information on these. * **Arrays:** Arrays are a data structure used to store collections of elements. Scala arrays are statically typed and can be initialized using the following syntax: ```scala var array1: Array[Type] = Array[Type](a0, a1, a2,...,an) var array2: Array[Type] = new Array[Type](n) ``` The first case initializes an array of specified size (n+1) with the provided elements. The second case initializes an empty array with a specified size (n). You can access or modify elements in the array using the index and the syntax `array(i)`. **Example: Accessing and modifying array elements** ```scala val array: Array[Int] = Array[Int](3, 2, 1, 3) array(2) = -4 // Modifying the element at index 2 for i <- 0 to array.length - 1 do println(array(i)) ``` This program takes a list of integers `(3, 2, 1, 3)`, modifies the element at index `2` to `-4`, and prints each element within the array. **IMPORTANT:** Arrays in Scala are mutable. While we are using the keyword *`val`*, this does not apply to the elements within the array. If you need to ensure the elements within the array cannot be changed, you can create an immutable array and call it using *`Array.apply(a0, a1, a2,...,an)`*. ### Objects * **Software Crisis:** Around 1965, there was much poorly structured code being written, so much so that software developers could no longer manage it effectively. This phenomenon led to the term *Software Crisis*. * **Goals of Good Software:** These are some of the goals that came out of attempts to alleviate the crisis: * **Controllability:** The ability to regulate and manage software's behavior. * **Maintainability:** The ability to modify and update software efficiently. * **Clarity:** Clear and understandable software code. * **Division of Labor:** Software development can be broken down and assigned to different teams. * **Expandability:** Software should be easy to add to and change. * **Error Prevention:** Preventions should be in place to catch bugs early on. * **Reusability:** Code should be easily reusable. * **Flexibility:** Software needs to be adaptable to changing needs. * **Object-Oriented Programming:** What came out of the software crisis were two attempts to solve it, functional programming and object-oriented programming, which focuses on structuring software by modeling the entities of the real world. **Key Concepts:** * **Objects:** A combination of data (attributes or properties) and methods (functions that work with the data) that models real-world entities. * **State:** The condition or set of values of an object's attributes at a given point in time. * **Identity:** A unique identifier for an object. * **Singleton Objects:** A specialized type of object where only one instance can exist. In Scala you use the `object` keyword to define a singleton object. **Example:** ```scala object Maaax: // attributes private var age: Int = 42 private var job: String = "Lecturer" // methods def getAge: Int = age def getJob: String = job def grow(): Unit = age = age + 1 def changeJob(newJob: String): Unit = job = newJob ``` * **Explanation:** The singleton object is created using the keyword `object`. Object names should start with a capital letter in Scala. We can store an object in a variable. For example: ```scala val m = Maaax ``` This line of code creates a variable named `m` that refers to the singleton object `Maaax`. The object `Maaax` has attributes like `age` and `job` and methods like `getAge`, `getJob`, `grow`, and `changeJob`. When declaring attributes, we use the `private` keyword. This makes the attributes accessible only within the object itself. Methods can be declared as `private`, which makes them only accessible within the object, or declared without the keyword, which makes them accessible within the object and in its environment. * **Accessor and Mutator Methods:** The object `Maaax` includes methods like `getAge` and `getJob`, which provide access to the object's attributes but do not modify them. There are also methods like `grow` and `changeJob` that modify the object's attributes. You can also use `override` within the object to override the predefined methods of a type like `toString` to produce a more readable output. ```scala override def toString: String = "Maaax(" + age.toString + ", " + job + ")" ``` ### Classes * **Class Definition:** A class acts as a blueprint for creating objects of the same type. It defines the attributes and methods the objects will have. Each object created from a class is called an instance of that class. **Example:** Creating a *`Lamp`* class and instantiating an object of that class: ```scala class Lamp(var power: Int): // primary constructor code here val l: Lamp = new Lamp(100) ``` The above code creates a `Lamp` class with a single constructor that takes an `Int` parameter representing lamp power. The variable `l` is assigned a new instance of the `Lamp` class with power set to `100`. You can have multiple constructors within a class for different use cases. You can accomplish this by creating a secondary constructor with different parameters within the class. * **Constructors:** Constructors are methods called when an object of a class is created, initializing its attributes. They can have parameters for customizing object creation. * **Destructors:** Destructors are methods responsible for releasing resources held by an object when it is no longer needed. These are not explicitly implemented in Scala because the garbage collector handles resource management. ### Methods and Attributes * **Attributes:** Data associated with an object. They can be declared as parameters in constructors or within the class code. * **Methods:** Functions that operate on an object's attributes. **Access Modifiers:** * **`private`:** Makes attributes and methods accessible only within the class itself. * **`protected`:** Makes attributes and methods accessible within its class and its subclasses. ### Requirements * **Requirements Check:** It is possible to validate requirements before an object is created using requirements. * **`require()` Method:** Ensures that parameters meet conditions. **Example:** Ensuring that the `power` attribute of the `Lamp` class is non-negative. ```scala class Lamp(var power: Int): require(power >= 0, "Power must be non-negative.") ``` ### The Signal Word *`this`* * **Secondary Constructors:** Used to initialize the object using alternate setup methods. * **Overloading:** Means having multiple constructors with different parameters. * **Calling Constructors:** The *`this`* keyword can be used within secondary constructors to call other constructors or methods within the class, specifying required parameters. ### Companion Objects * **Companion Object:** A Singleton object that has the same name as a class. It can access and modify the class's private attributes and methods, enabling controlled access. **Example:** Implementing a companion object for a `Student` class to manage student enrollment numbers: ```scala class Student(private val name: String, private val matr: Int): private val subject: String = "Bio Informatics" private var ects: Int = 0 // ... methods ... object Student: private var matrCounter: Int = 100 def resetMatrCounter(newCounter: Int): Unit = matrCounter = newCounter ``` * **Access:** The companion object (the object `Student` in this example) can directly access and modify the private attributes and methods of its corresponding class `Student`. The class `Student` can access the companion object's attributes and methods using `Student.attributeName` or `Student.methodName`. ### Inheritance * **Inheritance:** The mechanism where a subclass extends the attributes and methods of its superclass. **Terms:** * **Subclass:** The class inheriting from another class. * **Superclass:** The class from which another class inherits. * **Superclass Chain:** The hierarchy of classes where a subclass inherits from a superclass, which itself may inherit from another superclass, creating a chain of inheritance. **Example:** ```scala class Person(private val name: String, private var age: Int): def isGrownUp: Boolean = age >= 18 def work(): Unit = println("Work, work") class Student(name: String, age: Int, private val mat: Int) extends Person(name, age): def matNr: Int = mat override def work(): Unit = println("Study, Study") class Prof(name: String, age: Int, private var sal: Int) extends Person(name, age): def salary: Int = sal override def work(): Unit = println("Hold Monologue") ``` In the example above, `Person` is the superclass, and `Student` and `Prof` are subclasses that inherit from `Person`. The superclass `Person` has the attributes `name` and `age` and functions `isGrownUp` and `work`. The subclass `Student` has an additional attribute `mat`, and overrides the function `work()`, while the subclass `Prof` has an additional attribute `sal` and overrides the function `work()`. * **Inclusion Polymorphism:** A key concept in object-oriented programming where a subclass can be treated as an instance of its superclass due to inheritance relationships. **Example:** ```scala var p: Person = new Student("Anton", 19, 621637) ``` This demonstrates inclusion polymorphism in action. The variable `p` is declared as a `Person` object. However, we're able to assign an object of the `Student` class to it. Even though `p` is declared as a` Person` object, we can still access the `matNr()` method of the `Student` class through it, as demonstrated by: ```scala println(p.matNr) ``` The use of inheritance is an important aspect of object-oriented programming in Scala, allowing for the creation of well-structured and reusable code. **Note: ** This document only provides an introduction to some of the fundamentals of Object-Oriented programming in Scala. You should consult the Scala documentation for a complete and updated list of features and examples.