SlideShare a Scribd company logo
1 of 34
Download to read offline
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 1
Abstraction and Encapsulation
Abstraction: Abstract Methods - Abstract Class and its importance – implementation of
abstraction – Encapsulation: Packages - Access Modifiers – application of encapsulation -
Type Class and Conversions.
Abstraction
Abstraction is the process to hide the internal details and showing only the functionality. In
Scala, abstraction is achieved by using an abstract class. The working of the Scala abstract class
is similar to Java abstract class. In Scala, an abstract class is constructed using the abstract
keyword. It contains both abstract and non-abstract methods and cannot support multiple
inheritances. A class can extend only one abstract class.
Syntax:
abstract class class_name
{
// code..
}
The abstract methods of abstract class are those methods which do not contain any
implementation. Or in other words, the method which does not contain body is known as an
abstract method.
Syntax:
def function_name()
Example:
// Scala program to illustrate how to
// create an abstract class
// Abstract class
abstract class myauthor
{
// abstract method
def details()
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 2
// GFG class extends abstract class
class GFG extends myauthor
{
def details()
{
println("Author name: Ankita Saini")
println("Topic name: Abstract class in Scala")
}
}
object Main
{
// Main method
def main(args: Array[String])
{
// objects of GFG class
var obj = new GFG()
obj.details()
}
}
Following are some important observations about abstract classes in Scala;
in Scala, we are not allowed to create the instance of the abstract class. If we try to create objects
of the abstract class, then the compiler will give an error as shown in the below program.
// Scala program to illustrate // the concept of abstract class // Abstract class
abstract class myauthor{
// abstract method
def details()
}
object Main {
// Main method
def main(args: Array[String]) {
// Object of myauthor class
var obj = new myauthor()
}
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 3
In Scala, an abstract class can also contain fields. These fields are accessed by the abstract class
methods and by the methods of the class which inherit abstract class. As shown in the below
program.
// Scala program to illustrate
// the concept of abstract class
// Abstract class with fields
abstract class Geek
{
var name : String = "GeeksforGeeks"
var tutorial: String = "Scala"
def portal()
}
// GFG class extends abstract class
class GFG extends Geek
{
// Abstract class method accessing
// fields of the abstract class
def portal()
{
println("Portal name: " + name)
}
// GFG class method accessing
// fields of the abstract class
def tutdetails()
{
println("Tutorial name: " + tutorial)
}
}
object Main
{
// Main method
def main(args: Array[String])
{
// objects of GFG class
var obj = new GFG()
obj.portal()
obj.tutdetails()
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 4
}
}
Like Java, In Scala, an abstract class can also contain a constructor and a constructor of an
abstract class is called when an instance of a inherited class is created. As shown in the below
program.
// Scala program to illustrate
// the concept of abstract class
// Abstract class with constructor
// And the constructor contain two arguments
abstract class myauthor(name: String,
topic: String)
{
def details()
}
// GFG class extends abstract class
class GFG(name: String, topic: String) extends
myauthor(name, topic)
{
def details()
{
println("Author name: " + name)
println("Topic name: " + topic)
}
}
object Main
{
// Main method
def main(args: Array[String])
{
// objects of GFG class
var obj = new GFG("Ankita", "Abstract class")
obj.details()
}
}
An abstract class can also contain only non- abstract method. This allows us to create classes that
cannot be instantiated, but can only be inherited. As shown in the below program.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 5
// Scala program to illustrate
// the concept of abstract class
// Abstract class with
// non-abstract method
abstract class myauthor
{
// Non-abstract method
def details()
{
println("Welcome to GeeksforGeeks")
}
}
// GFG class extends abstract class
class GFG extends myauthor{}
object Main
{
// Main method
def main(args: Array[String])
{
// objects of GFG class
var obj = new GFG()
obj.details()
}
}
In Scala, an abstract class can contain final methods (methods that cannot be overridden). For
example, the following program compiles and runs without an error. In Scala, final method is
created using final keyword.
// Scala program to illustrate
// the concept of abstract class
// Abstract class with the final method
abstract class myauthor
{
final def mymethod()
{
println("Final method")
}
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 6
// GFG class extends abstract class
class GFG extends myauthor{}
object Main
{
// Main method
def main(args: Array[String])
{
// objects of GFG class
var obj = new GFG()
obj.mymethod()
}
}
When to use abstract class in Scala:
 An abstract class is useful:
 When we want to construct a base class which needs constructor arguments.
 When our code will be called from Java code.
Note:Traits are also used to achieve abstraction.
Abstract Class
 A class which is declared with abstract keyword is known as abstract class. An abstract
class can have abstract methods and non-abstract methods as well. Abstract class is used
to achieve abstraction. Abstraction is a process in which we hide complex
implementation details and show only functionality to the user.
 In scala, we can achieve abstraction by using abstract class and trait. We have discussed
about these in detail here.
Scala Abstract Class Example
 In this example, we have created a Bike abstract class. It contains an abstract method. A
class Hero extends it and provides implementation of its run method.
 A class that extends an abstract class must provide implementation of its all abstract
methods. You can't create object of an abstract class.
abstract class Bike{
def run()
}
class Hero extends Bike{
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 7
def run(){
println("running fine...")
}
}
object MainObject{
def main(args: Array[String]){
var h = new Hero()
h.run()
}
}
Abstract Class Example: Having Constructor, Variables and Abstract Methods
abstract class Bike(a:Int){ // Creating constructor
var b:Int = 20 // Creating variables
var c:Int = 25
def run() // Abstract method
def performance(){ // Non-abstract method
println("Performance awesome")
}
}
class Hero(a:Int) extends Bike(a){
c = 30
def run(){
println("Running fine...")
println("a = "+a)
println("b = "+b)
println("c = "+c)
}
}
object MainObject{
def main(args: Array[String]){
var h = new Hero(10)
h.run()
h.performance()
}
}
Scala Abstract Class Example: Abstract Method is not implemented
In this example, we didn't implement abstract method run(). Compiler reports an error during
compilation of this program. Error message is given below in output section.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 8
abstract class Bike{
def run() // Abstract method
}
class Hero extends Bike{ // Not implemented in this class
def runHero(){
println("Running fine...")
}
}
object MainObject{
def main(args: Array[String]){
var h = new Hero()
h.runHero()
}
}
Trait
 A trait is like an interface with a partial implementation. In scala, trait is a collection of
abstract and non-abstract methods. You can create trait that can have all abstract methods
or some abstract and some non-abstract methods.
 A variable that is declared either by using val or var keyword in a trait get internally
implemented in the class that implements the trait. Any variable which is declared by
using val or var but not initialized is considered abstract.
 Traits are compiled into Java interfaces with corresponding implementation classes that
hold any methods implemented in the traits.
Scala Trait Example
trait Printable{
def print()
}
class A4 extends Printable{
def print(){
println("Hello")
}
}
object MainObject{
def main(args:Array[String]){
var a = new A4()
a.print()
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 9
}
If a class extends a trait but does not implement the members declared in that trait, it must be
declared abstract. Let's see an example.
Scala Trait Example
trait Printable{
def print()
}
abstract class A4 extends Printable{ // Must declared as abstract class
def printA4(){
println("Hello, this is A4 Sheet")
}
}
Scala Trait Example: Implementing Multiple Traits in a Class
If a class implements multiple traits, it will extend the first trait, class, abstract class. with
keyword is used to extend rest of the traits.
You can achieve multiple inheritances by using trait.
trait Printable{
def print()
}
trait Showable{
def show()
}
class A6 extends Printable with Showable{
def print(){
println("This is printable")
}
def show(){
println("This is showable");
}
}
object MainObject{
def main(args:Array[String]){
var a = new A6()
a.print()
a.show()
}
}
Output:
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 10
This is printable
This is showable
Scala Trait having abstract and non-abstract methods
You can also define method in trait as like in abstract class. I.e. you can treat trait as abstract
class also. In scala, trait is almost same as abstract class except that it can't have constructor. You
can't extend multiple abstract classes but can extend multiple traits.
Scala Trait Example
trait Printable{
def print() // Abstract method
def show(){ // Non-abstract method
println("This is show method")
}
}
class A6 extends Printable{
def print(){
println("This is print method")
}
}
object MainObject{
def main(args:Array[String]){
var a = new A6()
a.print()
a.show()
}
}
Trait Mixins
 In scala, trait mixins means you can extend any number of traits with a class or abstract
class. You can extend only traits or combination of traits and class or traits and abstract
class.
 It is necessary to maintain order of mixins otherwise compiler throws an error.
 You can use mixins in scala like this:
Scala Trait Example: Mixins Order Not Maintained
In this example, we have extended a trait and an abstract class. Let's see what happen.
trait Print{
def print()
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 11
abstract class PrintA4{
def printA4()
}
class A6 extends Print with PrintA4{
def print(){ // Trait print
println("print sheet")
}
def printA4(){ // Abstract class printA4
println("Print A4 Sheet")
}
}
object MainObject{
def main(args:Array[String]){
var a = new A6()
a.print()
a.printA4()
}
}
Output:
error: class PrintA4 needs to be a trait to be mixed in
class A6 extends Print with PrintA4{
^
one error found
The above program throws a compile time error, because we didn't maintain mixins order.
Scala Mixins Order
The right mixins order of trait is that any class or abstract class which you want to extend, first
extend this. All the traits will be extended after this class or abstract class.
Scala Trait Example: Mixins Order Maintained
trait Print{
def print()
}
abstract class PrintA4{
def printA4()
}
class A6 extends PrintA4 with Print{ // First one is abstract class second one is trait
def print(){ // Trait print
println("print sheet")
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 12
def printA4(){ // Abstract class printA4
println("Print A4 Sheet")
}
}
object MainObject{
def main(args:Array[String]){
var a = new A6()
a.print()
a.printA4()
}
}
Output:
print sheet
Print A4 Sheet
Another Example of Scala Trait
Here, we have used one more approach to extend trait in our program. In this approach, we
extend trait during object creation. Let's see an example.
trait Print{
def print()
}
abstract class PrintA4{
def printA4()
}
class A6 extends PrintA4 {
def print(){ // Trait print
println("print sheet")
}
def printA4(){ // Abstract class printA4
println("Print A4 Sheet")
}
}
object MainObject{
def main(args:Array[String]){
var a = new A6() with Print // You can also extend trait during object creation
a.print()
a.printA4()
}
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 13
Encapsulation
Encapsulation is one of the fundamental concepts in object-oriented programming. It describes
the idea of bundling data and methods that work on that data within a class.
Let’s consider a class that represents a Sandwich:
import scala.collection.mutable.ArrayBuffer
class Sandwich(bread: Bread, filling: ArrayBuffer[String]) {
private def getFillingsName: String = {
filling.mkString(", ")
}
}
In the class definition, all properties and methods are private and we cannot access them from the
object we created. Doing so will result in a compilation error:
val sandwich = new Sandwich(new Bread("white"), ArrayBuffer("strawberry jam", "chocolate"))
sandwich.bread // error: value bread is not a member of Sandwich
sandwich.filling // error: value filling is not a member of Sandwich
sandwich.getFillingsName // error: method getFillingsName in class Sandwich cannot be
accessed in Sandwich
We can access or manipulate them with public methods:
def getDescription: String = {
s"This is a sandwich with ${bread.name} bread and $getFillingsName filling"
}
def addFilling(extraFilling: String): Unit = {
filling.append(extraFilling)
}
With the defined methods, now we can access and manipulate the private fields and methods of
the class:
val sandwich = new Sandwich(new Bread("sourdough"), ArrayBuffer("chicken"))
sandwich.addFilling("lettuce")
assert(sandwich.getDescription === "This is a sandwich with sourdough bread and chicken,
lettuce filling")
The Inner class means characterizing a class into another. This element empowers the users to
sensibly bunch classes that are just utilized in one place, subsequently this expands the utilization
of encapsulation, and make more creatable and viable code. In Scala, the idea of inner classes is
not the same as Java. Like in Java, the inner class is the member from the external class, yet in
Scala, the internal class is bound to the outer object.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 14
Use case 1:
// Outer class
class prwatech {
// Inner class
class P1
{
var a = 1
def method()
{
for(a<-0 to 2)
{
println("Welcome to Prwatech Data Science");
}
}
}
}
object Main
{
def main(args: Array[String])
{
// Creating object of the outer and
// inner class Here, P1 class is
// bounded with the object of Prwatech class
val obj = new prwatech();
val o = new obj.P1;
o.method();
}
}
Output
Welcome to Prwatech Data Science
Welcome to Prwatech Data Science
Welcome to Prwatech Data Science
Use case 2:
// Class inside Object
class outer_class_Prwatech
{
object inner_object_Prwatech1
{
val a = 0;
def method()
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 15
{
for(a <- 1 to 2)
{
println("object inside a class Prwatech")
}
println()
}
}
}
// Object inside Class
object outer_objectPrwatech
{
class innerPrwatech
{
val b = 0;
def method()
{
for(b <- 1 to 2)
{
println("class inside an object Prwatech")
}
}
}
}
object Main
{
// Main method
def main(args: Array[String])
{
// Object inside a class
new outer_class_Prwatech().inner_object_Prwatech1.method;
// Class inside an object
new outer_objectPrwatech.innerPrwatech().method;
}
}
Output
object inside a class Prwatech
object inside a class Prwatech
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 16
class inside an object Prwatech
class inside an object Prwatech
Use case 3:
class Prwatech
{
// Inner class
class P1
{
var x = 1
def method()
{
for(x<-0 to 0 )
{
println("Welcome to Prwatech");
}
}
}
}
object Main
{
def main(args: Array[String])
{
val obj = new Prwatech();
val o = new obj.P1;
o.method();
}
}
Packages
Package in Scala is a mechanism to encapsulate a group of classes, sub packages, traits and
package objects. It basically provides namespace to put our code in a different files and
directories. Packages is a easy way to maintain our code which prevents naming conflicts of
members of different packages. Providing access control to members of packages like private,
protected, package specific controlling scope restricts the access of member to other packages,
while the members with no modifier can be used inside any other package with some reference.
Declaration of Package
Packages are declared as a first statement at the top of a Scala file.
Syntax :
package package_name
// Scala classes
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 17
// traits
// objects..
Defining a package can be done in different ways:-
Chained methods
package x.y.z
// members of z
or can be used as:-
package x
package y
package z
// member of z
Nesting packages
package x{
// members of x {as required}
package y{
// members of y{as required}
package z{
// members of z{as required}
}
}
}
How Package works
Packages binds together the data in a single file or works as data encapsulation, when a file is
saved it comes under default package or under a package name as specified at the top of the file.
Package names and directory structure are closely related. For example if a package name is
college.student.cse, then there will be 3 directories, college, student and cse. Such that cse is
present in student and student is present in college.
college
+student
+cse
The idea is to make sure that files are easy to locate in directories while using the packages.
Package naming conventions for domain names are in reverse order as i.e.
org.geeksforgeeks.practice, org.geeksforgeeks.contribute.
Adding Members to Packages
We can add any numbers of members in a package such as classes, subclasses, traits, object
containing the main method and sub packages. Unlike the java packages we can add a declared
packages in different scala files i.e. different scala files can be written can for the same package.
Example:
// file named as faculty.scala
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 18
package college
class faculty{
def faculymethod(){}
}
// file named as student.scala
// containing the main method
// using the college package name again
package college
class student
{
def studentmethod(){}
}
// Creating object
object Main
{
// Main method
def main(args: Array[String])
{
val stu= new student()
val fac= new faculty()
// faculty class can be accessed while
// in different file but in same package.
}
}
What is actually created in directory structure is as below:-
college
+faculty.scala
+student.scala
Using Packages
Packages can be used by different ways in a program. Import clauses are quite flexible in Scala
than in java. Such as import clauses can be used any where in the program as an independent
statement in the program using the keyword import, Java does not allow that.
// base.scala
// bb directory
package bb
// creating a class
class geek
{
private var id=0
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 19
def method()
{
println("welcome to geek class")
println("id="+id)
}
}
Below is the example of Package using import clauses.
// main.scala
// aa directory
package aa
// Creating object
object Main
{
// Main method
def main(args: Array[String])
{
// importing in main method
import bb.geek
// using the member injected using import statement
val obj = new geek()
obj.method();
}
}
Different ways to use import statements
Importing all public members of package.
import college._
//imports all college members students, faculties, houseKeeping etc.
Imports only selected members of a package.
import college.{faculty, houseKeeping}
//member student is not selected hence cannot be used in current file
Imports and rename the members.
import college.{student => stu}
//stu is used in-place of student
Packages and Imports
 Scala uses packages to create namespaces which allow you to modularize programs.
Creating a package
 Packages are created by declaring one or more package names at the top of a Scala file.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 20
package users
class User
 One convention is to name the package the same as the directory containing the Scala
file. However, Scala is agnostic to file layout. The directory structure of an sbt project for
package users might look like this:
- ExampleProject
- build.sbt
- project
- src
- main
- scala
- users
User.scala
UserProfile.scala
UserPreferences.scala
- test
Notice how the users directory is within the scala directory and how there are multiple Scala files
within the package. Each Scala file in the package could have the same package declaration.
The other way to declare packages is by using braces:
package users {
package administrators {
class NormalUser
}
package normalusers {
class NormalUser
}
}
As you can see, this allows for package nesting and provides greater control for scope and
encapsulation.
The package name should be all lower case and if the code is being developed within an
organization which has a website, it should be the following format convention: <top-level-
domain>.<domain-name>.<project-name>. For example, if Google had a project called
SelfDrivingCar, the package name would look like this:
package com.google.selfdrivingcar.camera
class Lens
This could correspond to the following directory structure:
SelfDrivingCar/src/main/scala/com/google/selfdrivingcar/camera/Lens.scala.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 21
Imports
import clauses are for accessing members (classes, traits, functions, etc.) in other packages. An
import clause is not required for accessing members of the same package. Import clauses are
selective:
import users._ // import everything from the users package
import users.User // import the class User
import users.{User, UserPreferences} // Only imports selected members
import users.{UserPreferences => UPrefs} // import and rename for convenience
One way in which Scala is different from Java is that imports can be used anywhere:
def sqrtplus1(x: Int) = {
import scala.math.sqrt
sqrt(x) + 1.0
}
In the event there is a naming conflict and you need to import something from the root of the
project, prefix the package name with _root_:
package accounts
import _root_.users._
Package Objects
Package objects allow us to keep methods, functions, and variables directly aligned with a
package. As a result, all the child members of this package would be able to access them.
For each package, we are only allowed to create one package object where we put the source
code for the package in. According to the Scala convention, we should always call it
package.scala.
package com.baeldung.scala
package object packageimport {
val year = "2020"
trait Motor {
val dieselMessage: String = "I am not environment friendly"
val noDieselMessage: String = "I am environment friendly"
}
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 22
All members of com.baeldung.scala.package will be able to access year and Motor. In addition,
we won’t have to import package object in any of those members:
object bmwB38 extends Motor {
def run(): Unit =
println(s"I am a bmwB38 ! $noDieselMessage")
}
Access Modifier
Access modifier is used to define accessibility of data and our code to the outside world. You can
apply accessibly to classes, traits, data members, member methods and constructors etc. Scala
provides least accessibility to access to all. You can apply any access modifier to your code
according to your application requirement.
Scala provides only three types of access modifiers, which are given below:
In scala, if you don't mention any access modifier, it is treated as no modifier.
Scala Example: Private Access Modifier
In scala, private access modifier is used to make data accessible only within class in which it is
declared. It is most restricted and keeps your data in limited scope. Private data members does
not inherit into subclasses.
class AccessExample{
private var a:Int = 10
def show(){
println(a)
}
}
object MainObject{
def main(args:Array[String]){
var p = new AccessExample()
p.a = 12
p.show()
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 23
}
}
Output:
error: variable a in class AccessExample cannot be accessed in AccessExample
p.a = 12
^
one error found
Scala Example: Protected Access Modifier
Protected access modifier is accessible only within class, sub class and companion object. Data
members declared as protected are inherited in subclass. Let's see an example.
class AccessExample{
protected var a:Int = 10
}
class SubClass extends AccessExample{
def display(){
println("a = "+a)
}
}
object MainObject{
def main(args:Array[String]){
var s = new SubClass()
s.display()
}
}
Output:
a = 10
Scala Example: No-Access-Modifier
In scala, when you don't mention any access modifier, it is treated as no-access-modifier. It is
same as public in java. It is least restricted and can easily accessible from anywhere inside or
outside the package.
class AccessExample{
var a:Int = 10
def show(){
println(" a = "+a)
}
}
object MainObject{
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 24
def main(args:Array[String]){
var a = new AccessExample()
a.show()
}
}
There are Three types of access modifiers available in Scala:
1. Private
2. Protected
3. Public
1. Private: When a member is declared as private, we can only use it inside defining class or
through one of its objects.
Example:
// Scala program of private access modifier
class abc
{
private var a:Int = 123
def display()
{
a = 8
println(a)
}
}
object access extends App
{
// class abc is accessible
// because this is in the same enclosing scope
var e = new abc()
e.display()
}
Output:
8
Here we declared a variable ‘a’ private and now it can be accessed only inside it’s defining class
or through classes object.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 25
2. Protected: They can be only accessible from sub classes of the base class in which the
member has been defined.
Example:
// Scala program of protected access modifier
class gfg
{
// declaration of protected member
protected var a:Int = 123
def display()
{
a = 8
println(a)
}
}
// class new1 extends by class gfg
class new1 extends gfg
{
def display1()
{
a = 9
println(a)
}
}
object access extends App
{
// class abc is accessible because this
// is in the same enclosing scope
var e = new gfg()
e.display()
var e1 = new new1()
e1.display1()
}
Output:
8
9
When we extended abc in class new1, protected variable a is now available to be modified cause
new1 is a subclass of class abc.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 26
3. Public: There is no public keyword in Scala. The default access level (when no modifier is
specified) corresponds to Java’s public access level.We can access these anywhere.
// Scala program of protected access modifier
class gfg
{
var a:Int = 123
}
object access extends App
{
var e = new gfg()
e.a = 444
println(e.a)
}
Realtime Example of Encapsulation
Realtime Example 1:
School bag is one of the most real examples of Encapsulation. School bag can keep our books,
pens, etc.
Realtime Example 2:
When you log into your email accounts such as Gmail, Yahoo Mail, or Rediff mail, there is a lot
of internal processes taking place in the backend and you have no control over it.
When you enter the password for logging, they are retrieved in an encrypted form and verified,
and then you are given access to your account.
You do not have control over it that how the password has been verified. Thus, it keeps our
account safe from being misused.
Realtime Example 3:
Suppose you have an account in the bank. If your balance variable is declared as a public
variable in the bank software, your account balance will be known as public, In this case, anyone
can know your account balance. So, would you like it? Obviously No.
So, they declare balance variable as private for making your account safe, so that anyone cannot
see your account balance.
The person who has to see his account balance, will have to access only private members
through methods defined inside that class and this method will ask your account holder name or
user Id, and password for authentication.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 27
Thus, we can achieve security by utilizing the concept of data hiding. This is called
Encapsulation in Java.
How to achieve or implement Encapsulation
There are two important points whereby we can achieve or implement encapsulation in Java
program.
1. Declaring the instance variable of the class as private. so that it cannot be accessed directly by
anyone from outside the class.
2. Provide the public setter and getter methods in the class to set/modify the values of the
variable/fields.
Advantage of Encapsulation
There are following advantages of encapsulation in Java. They are as follows:
1. The encapsulated code is more flexible and easy to change with new requirements.
2. It prevents the other classes to access the private fields.
3. Encapsulation allows modifying implemented code without breaking other code that has
implemented the code.
4. It keeps the data and codes safe from external inheritance. Thus, Encapsulation helps to
achieve security.
5. It improves the maintainability of the application.
6. If you don’t define the setter method in the class then the fields can be made read-only.
7. If you don’t define the getter method in the class then the fields can be made write-only.
Disadvantage of Encapsulation
The main disadvantage of encapsulation in Java is it increases the length of the code and slows
shutdown execution.
Data Hiding
 Data hiding in Java is an important principle of object-oriented programming system
(OOPs). It prevents to access data members (variables) directly from outside the class so
that we can achieve security on data. This oops feature is called data hiding in Java.
 An outside person could not access our internal data directly or our internal data should
not go out directly. After validation or authentication, the outside person can access our
internal data.
 For example, after providing proper username and password, you can able to access your
Gmail inbox information.
How to achieve Data hiding programmatically?
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 28
By declaring data members (variables) as private, we can achieve or implement data hiding. If
the variables are declared as private in the class, nobody can access them from outside the class.
The biggest advantage of data hiding is we can achieve security.
Key points:
1. It is highly recommended to declare data members as private in the class.
2. A combination of data hiding and abstraction is nothing but encapsulation.
Encapsulation = Data Hiding + Abstraction
If any component follows data hiding and abstraction, it is called an encapsulated component.
Type Class
A type class is a group of types that satisfy a contract typically defined by a trait. They enable us
to make a function more ad-hoc polymorphic without touching its code. This flexibility is the
biggest win with the type-class pattern.
More formally put:
A type class is a type system construct that supports ad hoc polymorphism. This is achieved by
adding constraints to type variables in parametrically polymorphic types. Such a constraint
typically involves a type class T and a type variable a, and means that a can only be instantiated
to a type whose members support the overloaded operations associated with T
To unpack this definition, we need to identify the different terms used and define them
separately:
Type System – this is a logical system in the compiler that defines the rules for assigning the
property we call type to different programming constructs such as variables, expressions, or
functions. Int, String, and Long are the examples of types we are referring to here
Ad-hoc and Parametric Polymorphism – we covered these in our article about polymorphism in
Scala
Example Problem
Let’s create an extremely arbitrary example to see how we’d define and use type classes. Assume
we want to build a printing mechanism to display a couple of objects in a school information
system.
In the beginning, we have only StudentId, which wraps integer-based student IDs for type safety.
But with time, we expect to add several other data wrappers like StaffId, and even business
domain objects like Score, without touching the original implementation.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 29
The flexibility of the type-class pattern is exactly what we need here. So, let’s define these
objects:
case class StudentId(id: Int)
case class StaffId(id: Int)
case class Score(s: Double)
Since we’ve defined the problem, let’s go ahead and create a type-class to solve it. We’ll try to
reference the formal definition we quoted in the previous section so that it’s easy to map it to
implementation.
Defining Type Class T
In this section, we’ll define the type-class that provides the contract or constraint for our
solution:
trait Printer[A] {
def getString(a: A): String
}
We may find it a bit confusing that what we refer to as the type-class is only the trait, yet the
formal definition seems to imply there’s more. For clarity, let’s think of a type-class as a trait
applied in the context of what we referred to as the type-class constructor pattern. A trait on its
own or used in any other way does not qualify as a type-class.
As we saw earlier in the second sentence in the formal definition: This is achieved by adding
constraints to type variables in parametrically polymorphic types. In our case, the type class
above is the parametrically polymorphic type since we defined it with an unbounded type A,
meaning we can substitute A with any type when extending it.
Defining the Printer
The reason we use type classes is to make programs ad-hoc polymorphic, so let’s define the
function we want to apply it to:
def show[A](a: A)(implicit printer: Printer[A]): String = printer.getString(a)
We call the above function whenever we need to show data objects or wrappers in a human-
friendly manner. But we still haven’t empowered it to print anything since we haven’t defined
any type variables (a from the formal definition) for it.
Also notice that the method has two parameter lists. The first list contains ordinary functional
parameters, albeit abstract ones. The second parameter list has the printer parameter prefixed
with the implicit keyword. This should make sense after reading the article about implicit
classes.
Defining Type Variable a
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 30
Again, referring to the formal definition of a type-class, the last sentence reads: …a can only be
instantiated to a type whose members support the overloaded operations associated with T.
In our case, this simply means that our type variable should subtype the type-class Printer or
directly instantiate it so it can overload the getString method. By implication, the type variable
should also be implicit since that is how the show method expects it:
implicit val studentPrinter: Printer[StudentId] = new Printer[StudentId] {
def getString(a: StudentId): String = s"StudentId: ${a.id}"
}
At this stage, we can call show for StudentId types:
it should "print StudentId types" in {
val studentId = StudentId(25)
assertResult(expected = "StudentId: 25")(actual = show(studentId))
}
Extending the Type Class
So far, we have a working type-class implementation. In this section, we’ll see the flexibility of
type classes in action. We noted earlier that the type-class pattern enables us to achieve ad-hoc
polymorphism. This means that, without touching the show method, we can increase the range of
types it can handle.
We achieve a larger range by adding new type variables. In our case, we want to be able to print
StaffId and Score types such that the following test passes:
it should "custom print different types" in {
val studentId = StudentId(25)
val staffId = StaffId(12)
val score = Score(94.2)
assertResult(expected = "StudentId: 25")(actual = show(studentId))
assertResult(expected = "StaffId: 12")(actual = show(staffId))
assertResult(expected = "Score: 94.2%")(actual = show(score))
}
Now let’s define the necessary type variables. Typically, we group them in a companion object
(some people call the type-class pattern implicit objects for this reason):
object Printer {
implicit val studentPrinter: Printer[StudentId] = new Printer[StudentId] {
def getString(a: StudentId): String = s"StudentId: ${a.id}"
}
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 31
implicit val staffPrinter: Printer[StaffId] = new Printer[StaffId] {
def getString(a: StaffId): String = s"StaffId: ${a.id}"
}
implicit val scorePrinter: Printer[Score] = new Printer[Score] {
def getString(a: Score): String = s"Score: ${a.s}%"
}
}
That’s it. Any time we need to support new object types, we only need to add a type variable in
the Printer companion object.
Type Conversions
Types in Scala
Type also know as data type tells the compiler about the type of data that is used by the
programmer. For example, if we initialize a value or variable as an integer the compiler will free
up 4 bytes of memory space and it will hold 32 bit signed integer type.
Type Casting in Scala
 Type casting is the process of converting that type from one to another. For example, We
can convert int type to float type in Scala.
 But this conversion cannot be two ways and is derived from certain types i.e. the
conversion from one type to another is possible and the reverse is not. This is due to the
different sizes of data type and conversion from type of size greater to a smaller one
might lead to data losses.
The following conversions are valid:
Character -> Integer
Short -> Integer
Byte -> Integer
Integer -> Long
Long -> Float
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 32
Float -> Double
But, the reverse conversions can be done but are invalid due to data losses. For example,
Double -> Float is invalid.
Types of Type Casting
There can be two types of typecasting as all programming languages have,
 Implicit type casting
 Explicit type casting

1) Implicit type casting
In implicit type Casting of type in Scala the compiler itself cast the type of the
value/variable. This conversion can be lossy i.e. in some cases data may be lost. For
example, in the case of division of two int values which can return a non-integer (float/
double) value, the result will be of integer type which can lead to data loss.
Scala program to demonstrate example of implicit type casting
object myObject {
def main(args: Array[String]) {
val a : Int = 3421
println("a has value: " + a + " and its type is: " + a.getClass)
val c = a / 4 // result is 855.25 but will be converted to Int
println("The value of a/4: " + c + " and its type is: " + c.getClass)
}
}
Output:
a has value: 3421 and its type is: int
The value of a/4: 855 and its type is: int
In the above code, we have created a value a of type integer with value 3421, then we
have divided a by 4 and stored the result in value c. This division leaves to a decimal
point value but due to implicit type conversion, it is stored in integer type which two
losses.
This problem can be solved by using explicit conversion to avoid data loss but in some
cases that may lead to excessive memory wastage.
2) Explicit Type Conversion
The explicit type conversion is user-defined type conversion i.e. the user will decide that
final data type of the value/variable.
The type conversion of value types can be done directly but for reference types, the
conversion required asInstanceOf method.
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 33
As the asInstanceOf method is a concrete method of Any Class, it can be used for type
conversion of AnyVal object and AnyRef objects too (object conversion).
Let's see the examples of both the methods in action:
Example 1: Explicit type conversion
object myObject {
def main(args: Array[String]) {
// Type conversion from Short to Long
val a : Short = 3421
println("a has value: " + a + " and its type is: " + a.getClass)
val b : Long = a // converting type from short to long
println("Type casting from Short to Long")
println("b has value: " + b + " and its type is: " + b.getClass)
// Type conversion from Char to Float
val ch : Char = 'S'
println("nch has value: " + ch + " and its type is: " + ch.getClass)
val fl : Float = ch // converting type from Char to Float
println("Type casting from Character to Float")
println("fl has value: " + fl + " and its type is: " + fl.getClass)
}
}
Output:
a has value: 3421 and its type is: short
Type casting from Short to Long
b has value: 3421 and its type is: long
ch has value: S and its type is: char
Type casting from Character to Float
fl has value: 83.0 and its type is: float
In the above code, we have done two types of conversions. One from short to long and
other from char to float.
For short to long, we have created variable a of type short that stores a value 3421, and
then we have created another variable b of type long which is initialized with the value of
short.
For char to float, we have created variable ch of type char that stores a value S, and then
we have created another variable fl of type float which is initialized with the value of
char. This will have the float type of ASCII value of 'S'.
Example 2: Explicit conversion using asInstanceOf method
191AIC302T-Object Oriented Programming with SCALA
Unit-IV
Department of AI & DSPage 34
object myObject {
def main(args: Array[String]) {
// Type conversion from Short to Flaot
val a : Short = 3421
println("a has value: " + a + " and its type is: " + a.getClass)
val b = a.asInstanceOf[Double] // converting type from short to long
println("Type casting from Short to Double")
println("b has value: " + b + " and its type is: " + b.getClass)
// Type conversion from Char to Int
val ch : Char = 'S'
println("nch has value: " + ch + " and its type is: " + ch.getClass)
val intVal = ch.asInstanceOf[Int] // converting type from Char to Int
println("Type casting from Character to Int")
println("intVal has value: " + intVal + " and its type is: " + intVal.getClass)
}
}
Output:
a has value: 3421 and its type is: short
Type casting from Short to Double
b has value: 3421.0 and its type is: double
ch has value: S and its type is: char
Type casting from Character to Int
intVal has value: 83 and its type is: int
In the above code, we have done two types of conversions. One from short to Double and
other from char to int.
For short to Double, we have created variable a of type short that stores a value 3421, and
then we have created another variable b of type Double which is initialized using the
asInstanceOf method for conversion of type.
For char to float, we have created variable ch of type char that stores a value S, and then
we have created another variable intVal of type int which is initialized with the value of
char using the asInstanceOf method. The data in the intVal is the ASCII value for the
character.

More Related Content

Similar to Unit 4 notes.pdf

java-06inheritance
java-06inheritancejava-06inheritance
java-06inheritance
Arjun Shanka
 
Object Oriented Programming with Java
Object Oriented Programming with JavaObject Oriented Programming with Java
Object Oriented Programming with Java
backdoor
 

Similar to Unit 4 notes.pdf (20)

21UCAC31 Java Programming.pdf(MTNC)(BCA)
21UCAC31 Java Programming.pdf(MTNC)(BCA)21UCAC31 Java Programming.pdf(MTNC)(BCA)
21UCAC31 Java Programming.pdf(MTNC)(BCA)
 
Chap-3 Inheritance.pptx
Chap-3 Inheritance.pptxChap-3 Inheritance.pptx
Chap-3 Inheritance.pptx
 
Unit 3 notes.pdf
Unit 3 notes.pdfUnit 3 notes.pdf
Unit 3 notes.pdf
 
abstract,final,interface (1).pptx upload
abstract,final,interface (1).pptx uploadabstract,final,interface (1).pptx upload
abstract,final,interface (1).pptx upload
 
oops with java modules i & ii.ppt
oops with java modules i & ii.pptoops with java modules i & ii.ppt
oops with java modules i & ii.ppt
 
Qcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scalaQcon2011 functions rockpresentation_scala
Qcon2011 functions rockpresentation_scala
 
Unit 5 notes.pdf
Unit 5 notes.pdfUnit 5 notes.pdf
Unit 5 notes.pdf
 
Scala presentationjune112011
Scala presentationjune112011Scala presentationjune112011
Scala presentationjune112011
 
Inheritance and interface
Inheritance and interfaceInheritance and interface
Inheritance and interface
 
java-06inheritance
java-06inheritancejava-06inheritance
java-06inheritance
 
Java assignment help
Java assignment helpJava assignment help
Java assignment help
 
Object Oriented Programming with Java
Object Oriented Programming with JavaObject Oriented Programming with Java
Object Oriented Programming with Java
 
Object Oriented Programming using JAVA Notes
Object Oriented Programming using JAVA Notes Object Oriented Programming using JAVA Notes
Object Oriented Programming using JAVA Notes
 
Java
JavaJava
Java
 
Java Reflection Concept and Working
Java Reflection Concept and WorkingJava Reflection Concept and Working
Java Reflection Concept and Working
 
java: basics, user input, data type, constructor
java:  basics, user input, data type, constructorjava:  basics, user input, data type, constructor
java: basics, user input, data type, constructor
 
Chap-2 Classes & Methods.pptx
Chap-2 Classes & Methods.pptxChap-2 Classes & Methods.pptx
Chap-2 Classes & Methods.pptx
 
Oop2010 Scala Presentation Stal
Oop2010 Scala Presentation StalOop2010 Scala Presentation Stal
Oop2010 Scala Presentation Stal
 
Chapter 8 Inheritance
Chapter 8 InheritanceChapter 8 Inheritance
Chapter 8 Inheritance
 
Chapter 5 (OOP Principles).ppt
Chapter 5 (OOP Principles).pptChapter 5 (OOP Principles).ppt
Chapter 5 (OOP Principles).ppt
 

More from Revathiparamanathan (17)

UNIT 1 NOTES.docx
UNIT 1 NOTES.docxUNIT 1 NOTES.docx
UNIT 1 NOTES.docx
 
Unit 3,4.docx
Unit 3,4.docxUnit 3,4.docx
Unit 3,4.docx
 
UNIT II.docx
UNIT II.docxUNIT II.docx
UNIT II.docx
 
UNIT V.docx
UNIT V.docxUNIT V.docx
UNIT V.docx
 
COMPILER DESIGN.docx
COMPILER DESIGN.docxCOMPILER DESIGN.docx
COMPILER DESIGN.docx
 
UNIT -III.docx
UNIT -III.docxUNIT -III.docx
UNIT -III.docx
 
UNIT -IV.docx
UNIT -IV.docxUNIT -IV.docx
UNIT -IV.docx
 
UNIT - II.docx
UNIT - II.docxUNIT - II.docx
UNIT - II.docx
 
UNIT -V.docx
UNIT -V.docxUNIT -V.docx
UNIT -V.docx
 
UNIT - I.docx
UNIT - I.docxUNIT - I.docx
UNIT - I.docx
 
CC -Unit3.pptx
CC -Unit3.pptxCC -Unit3.pptx
CC -Unit3.pptx
 
CC -Unit4.pptx
CC -Unit4.pptxCC -Unit4.pptx
CC -Unit4.pptx
 
CC.pptx
CC.pptxCC.pptx
CC.pptx
 
Unit 1 notes.pdf
Unit 1 notes.pdfUnit 1 notes.pdf
Unit 1 notes.pdf
 
CC.pptx
CC.pptxCC.pptx
CC.pptx
 
Unit-4 Day1.pptx
Unit-4 Day1.pptxUnit-4 Day1.pptx
Unit-4 Day1.pptx
 
Scala Introduction.pptx
Scala Introduction.pptxScala Introduction.pptx
Scala Introduction.pptx
 

Recently uploaded

Integrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - NeometrixIntegrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - Neometrix
Neometrix_Engineering_Pvt_Ltd
 
Digital Communication Essentials: DPCM, DM, and ADM .pptx
Digital Communication Essentials: DPCM, DM, and ADM .pptxDigital Communication Essentials: DPCM, DM, and ADM .pptx
Digital Communication Essentials: DPCM, DM, and ADM .pptx
pritamlangde
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
AldoGarca30
 
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
9953056974 Low Rate Call Girls In Saket, Delhi NCR
 
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Kandungan 087776558899
 

Recently uploaded (20)

Integrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - NeometrixIntegrated Test Rig For HTFE-25 - Neometrix
Integrated Test Rig For HTFE-25 - Neometrix
 
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptxOrlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
Orlando’s Arnold Palmer Hospital Layout Strategy-1.pptx
 
Work-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptxWork-Permit-Receiver-in-Saudi-Aramco.pptx
Work-Permit-Receiver-in-Saudi-Aramco.pptx
 
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptxHOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
HOA1&2 - Module 3 - PREHISTORCI ARCHITECTURE OF KERALA.pptx
 
Digital Communication Essentials: DPCM, DM, and ADM .pptx
Digital Communication Essentials: DPCM, DM, and ADM .pptxDigital Communication Essentials: DPCM, DM, and ADM .pptx
Digital Communication Essentials: DPCM, DM, and ADM .pptx
 
A CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptx
A CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptxA CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptx
A CASE STUDY ON CERAMIC INDUSTRY OF BANGLADESH.pptx
 
Employee leave management system project.
Employee leave management system project.Employee leave management system project.
Employee leave management system project.
 
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
COST-EFFETIVE  and Energy Efficient BUILDINGS ptxCOST-EFFETIVE  and Energy Efficient BUILDINGS ptx
COST-EFFETIVE and Energy Efficient BUILDINGS ptx
 
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
1_Introduction + EAM Vocabulary + how to navigate in EAM.pdf
 
Introduction to Serverless with AWS Lambda
Introduction to Serverless with AWS LambdaIntroduction to Serverless with AWS Lambda
Introduction to Serverless with AWS Lambda
 
DC MACHINE-Motoring and generation, Armature circuit equation
DC MACHINE-Motoring and generation, Armature circuit equationDC MACHINE-Motoring and generation, Armature circuit equation
DC MACHINE-Motoring and generation, Armature circuit equation
 
Learn the concepts of Thermodynamics on Magic Marks
Learn the concepts of Thermodynamics on Magic MarksLearn the concepts of Thermodynamics on Magic Marks
Learn the concepts of Thermodynamics on Magic Marks
 
Moment Distribution Method For Btech Civil
Moment Distribution Method For Btech CivilMoment Distribution Method For Btech Civil
Moment Distribution Method For Btech Civil
 
Generative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPTGenerative AI or GenAI technology based PPT
Generative AI or GenAI technology based PPT
 
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
Call Girls in South Ex (delhi) call me [🔝9953056974🔝] escort service 24X7
 
Computer Networks Basics of Network Devices
Computer Networks  Basics of Network DevicesComputer Networks  Basics of Network Devices
Computer Networks Basics of Network Devices
 
School management system project Report.pdf
School management system project Report.pdfSchool management system project Report.pdf
School management system project Report.pdf
 
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak HamilCara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
Cara Menggugurkan Sperma Yang Masuk Rahim Biyar Tidak Hamil
 
data_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdfdata_management_and _data_science_cheat_sheet.pdf
data_management_and _data_science_cheat_sheet.pdf
 
Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...
Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...
Navigating Complexity: The Role of Trusted Partners and VIAS3D in Dassault Sy...
 

Unit 4 notes.pdf

  • 1. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 1 Abstraction and Encapsulation Abstraction: Abstract Methods - Abstract Class and its importance – implementation of abstraction – Encapsulation: Packages - Access Modifiers – application of encapsulation - Type Class and Conversions. Abstraction Abstraction is the process to hide the internal details and showing only the functionality. In Scala, abstraction is achieved by using an abstract class. The working of the Scala abstract class is similar to Java abstract class. In Scala, an abstract class is constructed using the abstract keyword. It contains both abstract and non-abstract methods and cannot support multiple inheritances. A class can extend only one abstract class. Syntax: abstract class class_name { // code.. } The abstract methods of abstract class are those methods which do not contain any implementation. Or in other words, the method which does not contain body is known as an abstract method. Syntax: def function_name() Example: // Scala program to illustrate how to // create an abstract class // Abstract class abstract class myauthor { // abstract method def details() }
  • 2. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 2 // GFG class extends abstract class class GFG extends myauthor { def details() { println("Author name: Ankita Saini") println("Topic name: Abstract class in Scala") } } object Main { // Main method def main(args: Array[String]) { // objects of GFG class var obj = new GFG() obj.details() } } Following are some important observations about abstract classes in Scala; in Scala, we are not allowed to create the instance of the abstract class. If we try to create objects of the abstract class, then the compiler will give an error as shown in the below program. // Scala program to illustrate // the concept of abstract class // Abstract class abstract class myauthor{ // abstract method def details() } object Main { // Main method def main(args: Array[String]) { // Object of myauthor class var obj = new myauthor() } }
  • 3. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 3 In Scala, an abstract class can also contain fields. These fields are accessed by the abstract class methods and by the methods of the class which inherit abstract class. As shown in the below program. // Scala program to illustrate // the concept of abstract class // Abstract class with fields abstract class Geek { var name : String = "GeeksforGeeks" var tutorial: String = "Scala" def portal() } // GFG class extends abstract class class GFG extends Geek { // Abstract class method accessing // fields of the abstract class def portal() { println("Portal name: " + name) } // GFG class method accessing // fields of the abstract class def tutdetails() { println("Tutorial name: " + tutorial) } } object Main { // Main method def main(args: Array[String]) { // objects of GFG class var obj = new GFG() obj.portal() obj.tutdetails()
  • 4. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 4 } } Like Java, In Scala, an abstract class can also contain a constructor and a constructor of an abstract class is called when an instance of a inherited class is created. As shown in the below program. // Scala program to illustrate // the concept of abstract class // Abstract class with constructor // And the constructor contain two arguments abstract class myauthor(name: String, topic: String) { def details() } // GFG class extends abstract class class GFG(name: String, topic: String) extends myauthor(name, topic) { def details() { println("Author name: " + name) println("Topic name: " + topic) } } object Main { // Main method def main(args: Array[String]) { // objects of GFG class var obj = new GFG("Ankita", "Abstract class") obj.details() } } An abstract class can also contain only non- abstract method. This allows us to create classes that cannot be instantiated, but can only be inherited. As shown in the below program.
  • 5. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 5 // Scala program to illustrate // the concept of abstract class // Abstract class with // non-abstract method abstract class myauthor { // Non-abstract method def details() { println("Welcome to GeeksforGeeks") } } // GFG class extends abstract class class GFG extends myauthor{} object Main { // Main method def main(args: Array[String]) { // objects of GFG class var obj = new GFG() obj.details() } } In Scala, an abstract class can contain final methods (methods that cannot be overridden). For example, the following program compiles and runs without an error. In Scala, final method is created using final keyword. // Scala program to illustrate // the concept of abstract class // Abstract class with the final method abstract class myauthor { final def mymethod() { println("Final method") } }
  • 6. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 6 // GFG class extends abstract class class GFG extends myauthor{} object Main { // Main method def main(args: Array[String]) { // objects of GFG class var obj = new GFG() obj.mymethod() } } When to use abstract class in Scala:  An abstract class is useful:  When we want to construct a base class which needs constructor arguments.  When our code will be called from Java code. Note:Traits are also used to achieve abstraction. Abstract Class  A class which is declared with abstract keyword is known as abstract class. An abstract class can have abstract methods and non-abstract methods as well. Abstract class is used to achieve abstraction. Abstraction is a process in which we hide complex implementation details and show only functionality to the user.  In scala, we can achieve abstraction by using abstract class and trait. We have discussed about these in detail here. Scala Abstract Class Example  In this example, we have created a Bike abstract class. It contains an abstract method. A class Hero extends it and provides implementation of its run method.  A class that extends an abstract class must provide implementation of its all abstract methods. You can't create object of an abstract class. abstract class Bike{ def run() } class Hero extends Bike{
  • 7. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 7 def run(){ println("running fine...") } } object MainObject{ def main(args: Array[String]){ var h = new Hero() h.run() } } Abstract Class Example: Having Constructor, Variables and Abstract Methods abstract class Bike(a:Int){ // Creating constructor var b:Int = 20 // Creating variables var c:Int = 25 def run() // Abstract method def performance(){ // Non-abstract method println("Performance awesome") } } class Hero(a:Int) extends Bike(a){ c = 30 def run(){ println("Running fine...") println("a = "+a) println("b = "+b) println("c = "+c) } } object MainObject{ def main(args: Array[String]){ var h = new Hero(10) h.run() h.performance() } } Scala Abstract Class Example: Abstract Method is not implemented In this example, we didn't implement abstract method run(). Compiler reports an error during compilation of this program. Error message is given below in output section.
  • 8. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 8 abstract class Bike{ def run() // Abstract method } class Hero extends Bike{ // Not implemented in this class def runHero(){ println("Running fine...") } } object MainObject{ def main(args: Array[String]){ var h = new Hero() h.runHero() } } Trait  A trait is like an interface with a partial implementation. In scala, trait is a collection of abstract and non-abstract methods. You can create trait that can have all abstract methods or some abstract and some non-abstract methods.  A variable that is declared either by using val or var keyword in a trait get internally implemented in the class that implements the trait. Any variable which is declared by using val or var but not initialized is considered abstract.  Traits are compiled into Java interfaces with corresponding implementation classes that hold any methods implemented in the traits. Scala Trait Example trait Printable{ def print() } class A4 extends Printable{ def print(){ println("Hello") } } object MainObject{ def main(args:Array[String]){ var a = new A4() a.print() }
  • 9. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 9 } If a class extends a trait but does not implement the members declared in that trait, it must be declared abstract. Let's see an example. Scala Trait Example trait Printable{ def print() } abstract class A4 extends Printable{ // Must declared as abstract class def printA4(){ println("Hello, this is A4 Sheet") } } Scala Trait Example: Implementing Multiple Traits in a Class If a class implements multiple traits, it will extend the first trait, class, abstract class. with keyword is used to extend rest of the traits. You can achieve multiple inheritances by using trait. trait Printable{ def print() } trait Showable{ def show() } class A6 extends Printable with Showable{ def print(){ println("This is printable") } def show(){ println("This is showable"); } } object MainObject{ def main(args:Array[String]){ var a = new A6() a.print() a.show() } } Output:
  • 10. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 10 This is printable This is showable Scala Trait having abstract and non-abstract methods You can also define method in trait as like in abstract class. I.e. you can treat trait as abstract class also. In scala, trait is almost same as abstract class except that it can't have constructor. You can't extend multiple abstract classes but can extend multiple traits. Scala Trait Example trait Printable{ def print() // Abstract method def show(){ // Non-abstract method println("This is show method") } } class A6 extends Printable{ def print(){ println("This is print method") } } object MainObject{ def main(args:Array[String]){ var a = new A6() a.print() a.show() } } Trait Mixins  In scala, trait mixins means you can extend any number of traits with a class or abstract class. You can extend only traits or combination of traits and class or traits and abstract class.  It is necessary to maintain order of mixins otherwise compiler throws an error.  You can use mixins in scala like this: Scala Trait Example: Mixins Order Not Maintained In this example, we have extended a trait and an abstract class. Let's see what happen. trait Print{ def print() }
  • 11. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 11 abstract class PrintA4{ def printA4() } class A6 extends Print with PrintA4{ def print(){ // Trait print println("print sheet") } def printA4(){ // Abstract class printA4 println("Print A4 Sheet") } } object MainObject{ def main(args:Array[String]){ var a = new A6() a.print() a.printA4() } } Output: error: class PrintA4 needs to be a trait to be mixed in class A6 extends Print with PrintA4{ ^ one error found The above program throws a compile time error, because we didn't maintain mixins order. Scala Mixins Order The right mixins order of trait is that any class or abstract class which you want to extend, first extend this. All the traits will be extended after this class or abstract class. Scala Trait Example: Mixins Order Maintained trait Print{ def print() } abstract class PrintA4{ def printA4() } class A6 extends PrintA4 with Print{ // First one is abstract class second one is trait def print(){ // Trait print println("print sheet") }
  • 12. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 12 def printA4(){ // Abstract class printA4 println("Print A4 Sheet") } } object MainObject{ def main(args:Array[String]){ var a = new A6() a.print() a.printA4() } } Output: print sheet Print A4 Sheet Another Example of Scala Trait Here, we have used one more approach to extend trait in our program. In this approach, we extend trait during object creation. Let's see an example. trait Print{ def print() } abstract class PrintA4{ def printA4() } class A6 extends PrintA4 { def print(){ // Trait print println("print sheet") } def printA4(){ // Abstract class printA4 println("Print A4 Sheet") } } object MainObject{ def main(args:Array[String]){ var a = new A6() with Print // You can also extend trait during object creation a.print() a.printA4() } }
  • 13. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 13 Encapsulation Encapsulation is one of the fundamental concepts in object-oriented programming. It describes the idea of bundling data and methods that work on that data within a class. Let’s consider a class that represents a Sandwich: import scala.collection.mutable.ArrayBuffer class Sandwich(bread: Bread, filling: ArrayBuffer[String]) { private def getFillingsName: String = { filling.mkString(", ") } } In the class definition, all properties and methods are private and we cannot access them from the object we created. Doing so will result in a compilation error: val sandwich = new Sandwich(new Bread("white"), ArrayBuffer("strawberry jam", "chocolate")) sandwich.bread // error: value bread is not a member of Sandwich sandwich.filling // error: value filling is not a member of Sandwich sandwich.getFillingsName // error: method getFillingsName in class Sandwich cannot be accessed in Sandwich We can access or manipulate them with public methods: def getDescription: String = { s"This is a sandwich with ${bread.name} bread and $getFillingsName filling" } def addFilling(extraFilling: String): Unit = { filling.append(extraFilling) } With the defined methods, now we can access and manipulate the private fields and methods of the class: val sandwich = new Sandwich(new Bread("sourdough"), ArrayBuffer("chicken")) sandwich.addFilling("lettuce") assert(sandwich.getDescription === "This is a sandwich with sourdough bread and chicken, lettuce filling") The Inner class means characterizing a class into another. This element empowers the users to sensibly bunch classes that are just utilized in one place, subsequently this expands the utilization of encapsulation, and make more creatable and viable code. In Scala, the idea of inner classes is not the same as Java. Like in Java, the inner class is the member from the external class, yet in Scala, the internal class is bound to the outer object.
  • 14. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 14 Use case 1: // Outer class class prwatech { // Inner class class P1 { var a = 1 def method() { for(a<-0 to 2) { println("Welcome to Prwatech Data Science"); } } } } object Main { def main(args: Array[String]) { // Creating object of the outer and // inner class Here, P1 class is // bounded with the object of Prwatech class val obj = new prwatech(); val o = new obj.P1; o.method(); } } Output Welcome to Prwatech Data Science Welcome to Prwatech Data Science Welcome to Prwatech Data Science Use case 2: // Class inside Object class outer_class_Prwatech { object inner_object_Prwatech1 { val a = 0; def method()
  • 15. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 15 { for(a <- 1 to 2) { println("object inside a class Prwatech") } println() } } } // Object inside Class object outer_objectPrwatech { class innerPrwatech { val b = 0; def method() { for(b <- 1 to 2) { println("class inside an object Prwatech") } } } } object Main { // Main method def main(args: Array[String]) { // Object inside a class new outer_class_Prwatech().inner_object_Prwatech1.method; // Class inside an object new outer_objectPrwatech.innerPrwatech().method; } } Output object inside a class Prwatech object inside a class Prwatech
  • 16. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 16 class inside an object Prwatech class inside an object Prwatech Use case 3: class Prwatech { // Inner class class P1 { var x = 1 def method() { for(x<-0 to 0 ) { println("Welcome to Prwatech"); } } } } object Main { def main(args: Array[String]) { val obj = new Prwatech(); val o = new obj.P1; o.method(); } } Packages Package in Scala is a mechanism to encapsulate a group of classes, sub packages, traits and package objects. It basically provides namespace to put our code in a different files and directories. Packages is a easy way to maintain our code which prevents naming conflicts of members of different packages. Providing access control to members of packages like private, protected, package specific controlling scope restricts the access of member to other packages, while the members with no modifier can be used inside any other package with some reference. Declaration of Package Packages are declared as a first statement at the top of a Scala file. Syntax : package package_name // Scala classes
  • 17. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 17 // traits // objects.. Defining a package can be done in different ways:- Chained methods package x.y.z // members of z or can be used as:- package x package y package z // member of z Nesting packages package x{ // members of x {as required} package y{ // members of y{as required} package z{ // members of z{as required} } } } How Package works Packages binds together the data in a single file or works as data encapsulation, when a file is saved it comes under default package or under a package name as specified at the top of the file. Package names and directory structure are closely related. For example if a package name is college.student.cse, then there will be 3 directories, college, student and cse. Such that cse is present in student and student is present in college. college +student +cse The idea is to make sure that files are easy to locate in directories while using the packages. Package naming conventions for domain names are in reverse order as i.e. org.geeksforgeeks.practice, org.geeksforgeeks.contribute. Adding Members to Packages We can add any numbers of members in a package such as classes, subclasses, traits, object containing the main method and sub packages. Unlike the java packages we can add a declared packages in different scala files i.e. different scala files can be written can for the same package. Example: // file named as faculty.scala
  • 18. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 18 package college class faculty{ def faculymethod(){} } // file named as student.scala // containing the main method // using the college package name again package college class student { def studentmethod(){} } // Creating object object Main { // Main method def main(args: Array[String]) { val stu= new student() val fac= new faculty() // faculty class can be accessed while // in different file but in same package. } } What is actually created in directory structure is as below:- college +faculty.scala +student.scala Using Packages Packages can be used by different ways in a program. Import clauses are quite flexible in Scala than in java. Such as import clauses can be used any where in the program as an independent statement in the program using the keyword import, Java does not allow that. // base.scala // bb directory package bb // creating a class class geek { private var id=0
  • 19. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 19 def method() { println("welcome to geek class") println("id="+id) } } Below is the example of Package using import clauses. // main.scala // aa directory package aa // Creating object object Main { // Main method def main(args: Array[String]) { // importing in main method import bb.geek // using the member injected using import statement val obj = new geek() obj.method(); } } Different ways to use import statements Importing all public members of package. import college._ //imports all college members students, faculties, houseKeeping etc. Imports only selected members of a package. import college.{faculty, houseKeeping} //member student is not selected hence cannot be used in current file Imports and rename the members. import college.{student => stu} //stu is used in-place of student Packages and Imports  Scala uses packages to create namespaces which allow you to modularize programs. Creating a package  Packages are created by declaring one or more package names at the top of a Scala file.
  • 20. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 20 package users class User  One convention is to name the package the same as the directory containing the Scala file. However, Scala is agnostic to file layout. The directory structure of an sbt project for package users might look like this: - ExampleProject - build.sbt - project - src - main - scala - users User.scala UserProfile.scala UserPreferences.scala - test Notice how the users directory is within the scala directory and how there are multiple Scala files within the package. Each Scala file in the package could have the same package declaration. The other way to declare packages is by using braces: package users { package administrators { class NormalUser } package normalusers { class NormalUser } } As you can see, this allows for package nesting and provides greater control for scope and encapsulation. The package name should be all lower case and if the code is being developed within an organization which has a website, it should be the following format convention: <top-level- domain>.<domain-name>.<project-name>. For example, if Google had a project called SelfDrivingCar, the package name would look like this: package com.google.selfdrivingcar.camera class Lens This could correspond to the following directory structure: SelfDrivingCar/src/main/scala/com/google/selfdrivingcar/camera/Lens.scala.
  • 21. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 21 Imports import clauses are for accessing members (classes, traits, functions, etc.) in other packages. An import clause is not required for accessing members of the same package. Import clauses are selective: import users._ // import everything from the users package import users.User // import the class User import users.{User, UserPreferences} // Only imports selected members import users.{UserPreferences => UPrefs} // import and rename for convenience One way in which Scala is different from Java is that imports can be used anywhere: def sqrtplus1(x: Int) = { import scala.math.sqrt sqrt(x) + 1.0 } In the event there is a naming conflict and you need to import something from the root of the project, prefix the package name with _root_: package accounts import _root_.users._ Package Objects Package objects allow us to keep methods, functions, and variables directly aligned with a package. As a result, all the child members of this package would be able to access them. For each package, we are only allowed to create one package object where we put the source code for the package in. According to the Scala convention, we should always call it package.scala. package com.baeldung.scala package object packageimport { val year = "2020" trait Motor { val dieselMessage: String = "I am not environment friendly" val noDieselMessage: String = "I am environment friendly" } }
  • 22. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 22 All members of com.baeldung.scala.package will be able to access year and Motor. In addition, we won’t have to import package object in any of those members: object bmwB38 extends Motor { def run(): Unit = println(s"I am a bmwB38 ! $noDieselMessage") } Access Modifier Access modifier is used to define accessibility of data and our code to the outside world. You can apply accessibly to classes, traits, data members, member methods and constructors etc. Scala provides least accessibility to access to all. You can apply any access modifier to your code according to your application requirement. Scala provides only three types of access modifiers, which are given below: In scala, if you don't mention any access modifier, it is treated as no modifier. Scala Example: Private Access Modifier In scala, private access modifier is used to make data accessible only within class in which it is declared. It is most restricted and keeps your data in limited scope. Private data members does not inherit into subclasses. class AccessExample{ private var a:Int = 10 def show(){ println(a) } } object MainObject{ def main(args:Array[String]){ var p = new AccessExample() p.a = 12 p.show()
  • 23. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 23 } } Output: error: variable a in class AccessExample cannot be accessed in AccessExample p.a = 12 ^ one error found Scala Example: Protected Access Modifier Protected access modifier is accessible only within class, sub class and companion object. Data members declared as protected are inherited in subclass. Let's see an example. class AccessExample{ protected var a:Int = 10 } class SubClass extends AccessExample{ def display(){ println("a = "+a) } } object MainObject{ def main(args:Array[String]){ var s = new SubClass() s.display() } } Output: a = 10 Scala Example: No-Access-Modifier In scala, when you don't mention any access modifier, it is treated as no-access-modifier. It is same as public in java. It is least restricted and can easily accessible from anywhere inside or outside the package. class AccessExample{ var a:Int = 10 def show(){ println(" a = "+a) } } object MainObject{
  • 24. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 24 def main(args:Array[String]){ var a = new AccessExample() a.show() } } There are Three types of access modifiers available in Scala: 1. Private 2. Protected 3. Public 1. Private: When a member is declared as private, we can only use it inside defining class or through one of its objects. Example: // Scala program of private access modifier class abc { private var a:Int = 123 def display() { a = 8 println(a) } } object access extends App { // class abc is accessible // because this is in the same enclosing scope var e = new abc() e.display() } Output: 8 Here we declared a variable ‘a’ private and now it can be accessed only inside it’s defining class or through classes object.
  • 25. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 25 2. Protected: They can be only accessible from sub classes of the base class in which the member has been defined. Example: // Scala program of protected access modifier class gfg { // declaration of protected member protected var a:Int = 123 def display() { a = 8 println(a) } } // class new1 extends by class gfg class new1 extends gfg { def display1() { a = 9 println(a) } } object access extends App { // class abc is accessible because this // is in the same enclosing scope var e = new gfg() e.display() var e1 = new new1() e1.display1() } Output: 8 9 When we extended abc in class new1, protected variable a is now available to be modified cause new1 is a subclass of class abc.
  • 26. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 26 3. Public: There is no public keyword in Scala. The default access level (when no modifier is specified) corresponds to Java’s public access level.We can access these anywhere. // Scala program of protected access modifier class gfg { var a:Int = 123 } object access extends App { var e = new gfg() e.a = 444 println(e.a) } Realtime Example of Encapsulation Realtime Example 1: School bag is one of the most real examples of Encapsulation. School bag can keep our books, pens, etc. Realtime Example 2: When you log into your email accounts such as Gmail, Yahoo Mail, or Rediff mail, there is a lot of internal processes taking place in the backend and you have no control over it. When you enter the password for logging, they are retrieved in an encrypted form and verified, and then you are given access to your account. You do not have control over it that how the password has been verified. Thus, it keeps our account safe from being misused. Realtime Example 3: Suppose you have an account in the bank. If your balance variable is declared as a public variable in the bank software, your account balance will be known as public, In this case, anyone can know your account balance. So, would you like it? Obviously No. So, they declare balance variable as private for making your account safe, so that anyone cannot see your account balance. The person who has to see his account balance, will have to access only private members through methods defined inside that class and this method will ask your account holder name or user Id, and password for authentication.
  • 27. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 27 Thus, we can achieve security by utilizing the concept of data hiding. This is called Encapsulation in Java. How to achieve or implement Encapsulation There are two important points whereby we can achieve or implement encapsulation in Java program. 1. Declaring the instance variable of the class as private. so that it cannot be accessed directly by anyone from outside the class. 2. Provide the public setter and getter methods in the class to set/modify the values of the variable/fields. Advantage of Encapsulation There are following advantages of encapsulation in Java. They are as follows: 1. The encapsulated code is more flexible and easy to change with new requirements. 2. It prevents the other classes to access the private fields. 3. Encapsulation allows modifying implemented code without breaking other code that has implemented the code. 4. It keeps the data and codes safe from external inheritance. Thus, Encapsulation helps to achieve security. 5. It improves the maintainability of the application. 6. If you don’t define the setter method in the class then the fields can be made read-only. 7. If you don’t define the getter method in the class then the fields can be made write-only. Disadvantage of Encapsulation The main disadvantage of encapsulation in Java is it increases the length of the code and slows shutdown execution. Data Hiding  Data hiding in Java is an important principle of object-oriented programming system (OOPs). It prevents to access data members (variables) directly from outside the class so that we can achieve security on data. This oops feature is called data hiding in Java.  An outside person could not access our internal data directly or our internal data should not go out directly. After validation or authentication, the outside person can access our internal data.  For example, after providing proper username and password, you can able to access your Gmail inbox information. How to achieve Data hiding programmatically?
  • 28. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 28 By declaring data members (variables) as private, we can achieve or implement data hiding. If the variables are declared as private in the class, nobody can access them from outside the class. The biggest advantage of data hiding is we can achieve security. Key points: 1. It is highly recommended to declare data members as private in the class. 2. A combination of data hiding and abstraction is nothing but encapsulation. Encapsulation = Data Hiding + Abstraction If any component follows data hiding and abstraction, it is called an encapsulated component. Type Class A type class is a group of types that satisfy a contract typically defined by a trait. They enable us to make a function more ad-hoc polymorphic without touching its code. This flexibility is the biggest win with the type-class pattern. More formally put: A type class is a type system construct that supports ad hoc polymorphism. This is achieved by adding constraints to type variables in parametrically polymorphic types. Such a constraint typically involves a type class T and a type variable a, and means that a can only be instantiated to a type whose members support the overloaded operations associated with T To unpack this definition, we need to identify the different terms used and define them separately: Type System – this is a logical system in the compiler that defines the rules for assigning the property we call type to different programming constructs such as variables, expressions, or functions. Int, String, and Long are the examples of types we are referring to here Ad-hoc and Parametric Polymorphism – we covered these in our article about polymorphism in Scala Example Problem Let’s create an extremely arbitrary example to see how we’d define and use type classes. Assume we want to build a printing mechanism to display a couple of objects in a school information system. In the beginning, we have only StudentId, which wraps integer-based student IDs for type safety. But with time, we expect to add several other data wrappers like StaffId, and even business domain objects like Score, without touching the original implementation.
  • 29. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 29 The flexibility of the type-class pattern is exactly what we need here. So, let’s define these objects: case class StudentId(id: Int) case class StaffId(id: Int) case class Score(s: Double) Since we’ve defined the problem, let’s go ahead and create a type-class to solve it. We’ll try to reference the formal definition we quoted in the previous section so that it’s easy to map it to implementation. Defining Type Class T In this section, we’ll define the type-class that provides the contract or constraint for our solution: trait Printer[A] { def getString(a: A): String } We may find it a bit confusing that what we refer to as the type-class is only the trait, yet the formal definition seems to imply there’s more. For clarity, let’s think of a type-class as a trait applied in the context of what we referred to as the type-class constructor pattern. A trait on its own or used in any other way does not qualify as a type-class. As we saw earlier in the second sentence in the formal definition: This is achieved by adding constraints to type variables in parametrically polymorphic types. In our case, the type class above is the parametrically polymorphic type since we defined it with an unbounded type A, meaning we can substitute A with any type when extending it. Defining the Printer The reason we use type classes is to make programs ad-hoc polymorphic, so let’s define the function we want to apply it to: def show[A](a: A)(implicit printer: Printer[A]): String = printer.getString(a) We call the above function whenever we need to show data objects or wrappers in a human- friendly manner. But we still haven’t empowered it to print anything since we haven’t defined any type variables (a from the formal definition) for it. Also notice that the method has two parameter lists. The first list contains ordinary functional parameters, albeit abstract ones. The second parameter list has the printer parameter prefixed with the implicit keyword. This should make sense after reading the article about implicit classes. Defining Type Variable a
  • 30. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 30 Again, referring to the formal definition of a type-class, the last sentence reads: …a can only be instantiated to a type whose members support the overloaded operations associated with T. In our case, this simply means that our type variable should subtype the type-class Printer or directly instantiate it so it can overload the getString method. By implication, the type variable should also be implicit since that is how the show method expects it: implicit val studentPrinter: Printer[StudentId] = new Printer[StudentId] { def getString(a: StudentId): String = s"StudentId: ${a.id}" } At this stage, we can call show for StudentId types: it should "print StudentId types" in { val studentId = StudentId(25) assertResult(expected = "StudentId: 25")(actual = show(studentId)) } Extending the Type Class So far, we have a working type-class implementation. In this section, we’ll see the flexibility of type classes in action. We noted earlier that the type-class pattern enables us to achieve ad-hoc polymorphism. This means that, without touching the show method, we can increase the range of types it can handle. We achieve a larger range by adding new type variables. In our case, we want to be able to print StaffId and Score types such that the following test passes: it should "custom print different types" in { val studentId = StudentId(25) val staffId = StaffId(12) val score = Score(94.2) assertResult(expected = "StudentId: 25")(actual = show(studentId)) assertResult(expected = "StaffId: 12")(actual = show(staffId)) assertResult(expected = "Score: 94.2%")(actual = show(score)) } Now let’s define the necessary type variables. Typically, we group them in a companion object (some people call the type-class pattern implicit objects for this reason): object Printer { implicit val studentPrinter: Printer[StudentId] = new Printer[StudentId] { def getString(a: StudentId): String = s"StudentId: ${a.id}" }
  • 31. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 31 implicit val staffPrinter: Printer[StaffId] = new Printer[StaffId] { def getString(a: StaffId): String = s"StaffId: ${a.id}" } implicit val scorePrinter: Printer[Score] = new Printer[Score] { def getString(a: Score): String = s"Score: ${a.s}%" } } That’s it. Any time we need to support new object types, we only need to add a type variable in the Printer companion object. Type Conversions Types in Scala Type also know as data type tells the compiler about the type of data that is used by the programmer. For example, if we initialize a value or variable as an integer the compiler will free up 4 bytes of memory space and it will hold 32 bit signed integer type. Type Casting in Scala  Type casting is the process of converting that type from one to another. For example, We can convert int type to float type in Scala.  But this conversion cannot be two ways and is derived from certain types i.e. the conversion from one type to another is possible and the reverse is not. This is due to the different sizes of data type and conversion from type of size greater to a smaller one might lead to data losses. The following conversions are valid: Character -> Integer Short -> Integer Byte -> Integer Integer -> Long Long -> Float
  • 32. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 32 Float -> Double But, the reverse conversions can be done but are invalid due to data losses. For example, Double -> Float is invalid. Types of Type Casting There can be two types of typecasting as all programming languages have,  Implicit type casting  Explicit type casting  1) Implicit type casting In implicit type Casting of type in Scala the compiler itself cast the type of the value/variable. This conversion can be lossy i.e. in some cases data may be lost. For example, in the case of division of two int values which can return a non-integer (float/ double) value, the result will be of integer type which can lead to data loss. Scala program to demonstrate example of implicit type casting object myObject { def main(args: Array[String]) { val a : Int = 3421 println("a has value: " + a + " and its type is: " + a.getClass) val c = a / 4 // result is 855.25 but will be converted to Int println("The value of a/4: " + c + " and its type is: " + c.getClass) } } Output: a has value: 3421 and its type is: int The value of a/4: 855 and its type is: int In the above code, we have created a value a of type integer with value 3421, then we have divided a by 4 and stored the result in value c. This division leaves to a decimal point value but due to implicit type conversion, it is stored in integer type which two losses. This problem can be solved by using explicit conversion to avoid data loss but in some cases that may lead to excessive memory wastage. 2) Explicit Type Conversion The explicit type conversion is user-defined type conversion i.e. the user will decide that final data type of the value/variable. The type conversion of value types can be done directly but for reference types, the conversion required asInstanceOf method.
  • 33. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 33 As the asInstanceOf method is a concrete method of Any Class, it can be used for type conversion of AnyVal object and AnyRef objects too (object conversion). Let's see the examples of both the methods in action: Example 1: Explicit type conversion object myObject { def main(args: Array[String]) { // Type conversion from Short to Long val a : Short = 3421 println("a has value: " + a + " and its type is: " + a.getClass) val b : Long = a // converting type from short to long println("Type casting from Short to Long") println("b has value: " + b + " and its type is: " + b.getClass) // Type conversion from Char to Float val ch : Char = 'S' println("nch has value: " + ch + " and its type is: " + ch.getClass) val fl : Float = ch // converting type from Char to Float println("Type casting from Character to Float") println("fl has value: " + fl + " and its type is: " + fl.getClass) } } Output: a has value: 3421 and its type is: short Type casting from Short to Long b has value: 3421 and its type is: long ch has value: S and its type is: char Type casting from Character to Float fl has value: 83.0 and its type is: float In the above code, we have done two types of conversions. One from short to long and other from char to float. For short to long, we have created variable a of type short that stores a value 3421, and then we have created another variable b of type long which is initialized with the value of short. For char to float, we have created variable ch of type char that stores a value S, and then we have created another variable fl of type float which is initialized with the value of char. This will have the float type of ASCII value of 'S'. Example 2: Explicit conversion using asInstanceOf method
  • 34. 191AIC302T-Object Oriented Programming with SCALA Unit-IV Department of AI & DSPage 34 object myObject { def main(args: Array[String]) { // Type conversion from Short to Flaot val a : Short = 3421 println("a has value: " + a + " and its type is: " + a.getClass) val b = a.asInstanceOf[Double] // converting type from short to long println("Type casting from Short to Double") println("b has value: " + b + " and its type is: " + b.getClass) // Type conversion from Char to Int val ch : Char = 'S' println("nch has value: " + ch + " and its type is: " + ch.getClass) val intVal = ch.asInstanceOf[Int] // converting type from Char to Int println("Type casting from Character to Int") println("intVal has value: " + intVal + " and its type is: " + intVal.getClass) } } Output: a has value: 3421 and its type is: short Type casting from Short to Double b has value: 3421.0 and its type is: double ch has value: S and its type is: char Type casting from Character to Int intVal has value: 83 and its type is: int In the above code, we have done two types of conversions. One from short to Double and other from char to int. For short to Double, we have created variable a of type short that stores a value 3421, and then we have created another variable b of type Double which is initialized using the asInstanceOf method for conversion of type. For char to float, we have created variable ch of type char that stores a value S, and then we have created another variable intVal of type int which is initialized with the value of char using the asInstanceOf method. The data in the intVal is the ASCII value for the character.