SlideShare a Scribd company logo
1 of 20
Download to read offline
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 1
Inheritance and Polymorphism
Inheritance: Defining derived classes & Visibility modes – Types of Inheritance: Single-
level Inheritance - Multilevel Inheritance - Multiple Inheritance - Hierarchical Inheritance
- Hybrid Inheritance – Inheritance vs Composition – Polymorphism: Types of
Polymorphism - Parametric Polymorphism - Subtype Polymorphism - Ad-Hoc
Polymorphism - Function Overloading - Operator Overloading.
Inheritance:
Inheritance in Scala is the concept of inheriting values and properties by one object from
another object.
Scala programming language is a programming language that integrates features of both object-
oriented programming and function programming supports inheritance too, as it is a really
important feature of OOP's concept.
Before going ahead, let's see some key terms related to inheritance in Scala,
 Super Class is also known as base class or parent class. It is the class whose features are
inherited by other classes.
 Sub Class is also known as child class, derived class, or extended class. It is the class that
inherits features from other classes.
To implement the concepts of inheritance we need to understand the working of some keywords
in Scala:
 extends: The extends keyword in Scala is used to inherit features of one class by another
class.
baseClass extends parentClass
This extends keyword is used to inherit class while creating a new one.
 With: the with keyword in Scala is used when we need to inherit more than one class by
another class.
Syntax
class SubClassName extends SuperClassName(){
/* Write your code
* methods and fields etc.
*/
}
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 2
Types of Inheritances in Scala
While inheriting classes in Scala, there can be multiple ways to inherit classes.
Here are types of inheritance in Scala:
1. Single Inheritance
2. Multiple Inheritance
3. Multilevel Inheritance
4. Hierarchical Inheritance
5. Hybrid Inheritance
1. Single Inheritance
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 3
 Single inheritance is a type of inheritance in which one class is inherited by another class.
 The concept is depicted in the following diagram,
Here, in single inheritance, one class is simply inherited by another class in Scala.
Example:
class class1{
var value1 = 935
}
class class2 extends class1{
val value2 = 54
def printValues(){
println("Value 1: " + value1 )
println("Value 2: " + value2 )
println("Sum: " + (value1 + value2))
}
}
object MyClass {
def main(args: Array[String]) {
val object1 = new class2();
object1.printValues()
}
}
Multiple Inheritance
Multiple inheritance is a type of inheritance in which multiple classes are inherited by one class
at a time.
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 4
Example:
trait baseClass1{
var value1 = 935
}
trait baseClass2{
var value2 = 43
}
class derivedClass extends baseClass1 with baseClass2{
def printValues(){
println("Derived Class")
println("Value 1 : " + value1 )
println("Value 2 : " + value2 )
println("Concatination : " + (value1 + value2) )
}
}
object MyClass {
def main(args: Array[String]) {
val object1 = new derivedClass();
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 5
object1.printValues()
}
}
Multilevel Inheritance
 Multi-Level inheritance is a type of inheritance in which one class is inherited by another
class which is in turn inherited by the third class.
 The concept is depicted in the following diagram,
Example:
class class1{
var value1 = 935
}
class class2 extends class1{
val value2 = 54
}
class class3 extends class2{
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 6
def printValues(){
println("Value 1: " + value1 )
println("Value 2: " + value2 )
println("Sum: " + (value1 + value2))
}
}
object MyClass {
def main(args: Array[String]) {
val object1 = new class3();
object1.printValues()
}
}
Hierarchical Inheritance
 Hierarchical inheritance is a type of inheritance in which one class is inherited by more
than one class.
 The concept is depicted in the following diagram,
Example:
class baseClass{
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 7
var value1 = 935
}
class derivedClass1 extends baseClass{
def printValues(){
println("nDerived Class 1")
val value2 = 54
println("Value 1: " + value1)
println("Value 2: " + value2)
println("Sum: " + (value1 + value2))
}
}
class derivedClass2 extends baseClass{
def printValues(){
val value2 = 341
println("nDerived Class 2")
println("Value 1 : " + value1 )
println("Value 2 : " + value2 )
println("Concatination : " + value1 + value2 )
}
}
object MyClass {
def main(args: Array[String]) {
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 8
val object1 = new derivedClass1();
object1.printValues()
val object2 = new derivedClass2();
object2.printValues()
}
}
Hybrid Inheritance
 Hybrid Inheritance is a special type of inheritance which is a combination of hierarchical
and multiple inheritance in Scala.
class A {
var numA: Int = 0;
def setA(n: Int) {
numA = n;
}
def printA() {
printf("numA: %dn", numA);
}
}
class B extends A {
var numB: Int = 0;
def setB(n: Int) {
numB = n;
}
def printB() {
printf("numB: %dn", numB);
}
}
class C extends B {
var numC: Int = 0;
def setC(n: Int) {
numC = n;
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 9
}
def printC() {
printf("numC: %dn", numC);
}
}
class D extends A {
var numD: Int = 0;
def setD(n: Int) {
numD = n;
}
def printD() {
printf("numD: %dn", numD);
}
}
object Sample {
def main(args: Array[String]) {
var obj1 = new C();
var obj2 = new D();
obj1.setA(10);
obj1.setB(20);
obj1.setC(30);
obj1.printA();
obj1.printB();
obj1.printC();
obj2.setA(40);
obj2.setD(50);
obj2.printA();
obj2.printD();
}
}
Inheritance vs Composition:
Composition and inheritance are two ways to define a new class in terms of another existing
class. If what you're after is primarily code reuse, you should in general prefer composition to
inheritance. Only inheritance suffers from the fragile base class problem, in which you can
inadvertently break subclasses by changing a superclass.
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 10
One question you can ask yourself about an inheritance relationship is whether it models an is-a
relationship.[8] For example, it would be reasonable to say that ArrayElement is-an Element.
Another question you can ask is whether clients will want to use the subclass type as a
superclass type.[9] In the case of ArrayElement, we do indeed expect clients will want to use an
ArrayElement as an Element.
If you ask these questions about the inheritance relationships shown in Figure 10.3, do any of
the relationships seem suspicious? In particular, does it seem obvious to you that a LineElement
is-an ArrayElement? Do you think clients would ever need to use a LineElement as an
ArrayElement? In fact, we defined LineElement as a subclass of ArrayElement primarily to
reuse ArrayElement's definition of contents. Perhaps it would be better, therefore, to define
LineElement as a direct subclass of Element, like this:
class LineElement(s: String) extends Element {
val contents = Array(s)
override def width = s.length
override def height = 1
}
What is Inheritance?
Inheritance is one of the most powerful tools in implementing code reusability in object-
oriented programming. It refers to the functionality by which one object acquires the
characteristics of one or more other objects. Inheritance in C++ means you can create classes
that derive their attributes from existing classes. This means you specialize a class to create an
is-a relationship between the classes which results in a strong coupling between the base and
derived classes. Implementing inheritance promotes code reusability because new classes are
created from existing classes. Class inheritance also makes it easier to modify the
implementation being reused. But class inheritance has some downsides to it too. First, because
inheritance is defined at compile-time, you cannot change the implementations inherited from
parent classes at run-time.
What is Composition?
OOP provides yet another relationship between classes called composition, which is also known
as a has-a relationship. If the features of one object need to be a part of another object, the
relationship calls for composition. To compose a class from existing classes, an object of each
class should be declared as the member of the new class. In simple words, using an object
within another object is known as composition. Many a times, you might want to use an object
as a field within another class. You use an object inside a class in composition. Unlike class
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 11
inheritance, object composition is defined dynamically at run-time through objects acquiring
references to other objects. Additionally, composition provides a better way to use an object
without compromising the internal details of the object, that is where composition is useful.
Difference between Composition and Inheritance
Approach
While both inheritance and composition promote code reusability in object oriented system by
establishing relationships between classes and they provide equivalent functionality in many
ways, they use different approaches. With inheritance, you can create classes that derive their
attributes from existing classes so while using inheritance to create a class, you can expand on
an existing class. On the contrary, using an object within another object is known as
composition. Object composition is an alternative to class inheritance. If the features of one
object need to be a part of another object, the relationship calls for composition.
Relationship
In inheritance, you specialize a class to create an “is-a” relationship between the classes which
results in a strong coupling between the base and derived classes. It enables a hierarchy of
classes to be designed and the hierarchy begins with the most general class and moves to more
specific classes. By implementing inheritance, member functions from one class become
properties of another class without coding them explicitly within the class. In composition, you
use an object inside a class and any requests to the object are forwarded to the object. The
internal details are not exposed to each other in composition, so it is a “has-a” relationship.
Implementation
Class inheritance is defined at compile-time, so you cannot change the implementations
inherited from parent classes at run-time. Because inheritance exposes a subclass to details of its
parent’s implementation, it often breaks encapsulation. Any changes in the parent class will
reflect in the subclass which can create problems when you try to reuse a subclass. Object
composition, on the contrary, is defined dynamically at run-time through objects acquiring
references to other objects. And because objects are accessed solely through their interfaces, it
won’t break encapsulation. Any object can be replaced at run-time by another object as long as
it has the same type.
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 12
Polymorphism
 In the simplest of terms, polymorphism means one object having many forms or an
object’s ability to exhibit multiple behaviors. In computer terms, this would show up as
handling different data types using the same interface or method.
 The more formal definition is: polymorphism is the provision of a single interface to
entities of different types or the use of a single symbol to represent multiple different
types.
 Polymorphism means that a function type comes "in many forms".
 In programming it means that the function can be applied to arguments of many types, or
the type can have instances of many types.
Consider the following class hierarchy:
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 13
Example:
trait Animal {
def fitness: Int
}
trait Reptile extends Animal
trait Mammal extends Animal
trait Zebra extends Mammal {
def zebraCount: Int
}
trait Giraffe extends Mammal
Parametric Polymorphism
If we’re to take only one statement from this section, it’s that parametric polymorphism is
just generics as used in languages such as Java, C#, and Scala.
We can easily recognize parametrically polymorphic functions in Scala by the presence of
one or more type parameters delimited by square brackets in the method signature — they
enable us to apply the same logic to different data types.
Let’s look at an example to illustrate this. Imagine we’re writing a method to pair-wise
reverse a List. We want to be able to input List(1,2,3,4,5,6) and get output List(2,1,4,3,6,5).
If the length is odd, then the last element should stay in its place such that List(1,2,3,4,5)
becomes List(2,1,4,3,5).
The Naive Solution
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 14
def pairWiseReverseInt(xs: List[Int]): List[Int] = xs.grouped(2).flatMap(_.reverse).toList
Let’s create a test for the above scenario:
it should "reverse an even length int list" in {
val input = List(1,2,3,4,5,6)
val expected = List(2,1,4,3,5,6)
val actual = pairWiseReverseInt(input)
assert(actual == expected)
}
The method we’ve written works well for integer arrays but is not reusable for other types.
As an example, if we’d like to pair-wise reverse a list of strings or doubles, we’d have to
create additional methods and pointlessly duplicate the logic:
def pairWiseReverseString(xs: List[String]): List[String] =
arr.grouped(2).flatMap(_.reverse).toList
it should "pair-wise reverse a string list" in {
val original = List("a","b","c","d","e")
val expected = List("b","a","d","c","e")
val actual = pairWiseReverseString(original)
assertResult(expected)(actual)
}
The DRY Solution
Parametric polymorphism helps us eliminate this unnecessary duplication of code by
introducing a second formal parameter list for type parameters. With parametric
polymorphism, the logic remains the same for all the different types. To illustrate, we’ll
refactor the above pair-wise reverse methods into one that works for all types:
def pairWiseReverse[A](xs:List[A]): List[A] = xs.grouped(2).flatMap(_.reverse).toList
We’ve represented the type parameter by letter A, but we could just as well have used K, T,
or any other letter — it doesn’t matter. As with all formal parameters, we expect to substitute
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 15
A during a method call with a concrete type such as Int, String, or any other concrete type in
our case:
it should "pair-wise reverse lists of any type" in {
val originalInts = List(1,2,3,4,5)
val expectedInts = List(2,1,4,3,5)
val originalStrings = List("a","b","c","d","e")
val expectedStrings = List("b","a","d","c","e")
val originalDoubles = List(1.2,2.7,3.4,4.3,5.0)
val expectedDoubles = List(2.7,1.2,4.3,3.4,5.0)
assertResult(expectedInts)(pairWiseReverse[Int](originalInts))
assertResult(expectedStrings)(pairWiseReverse[String](originalStrings))
assertResult(expectedDoubles)(pairWiseReverse[Double](originalDoubles))
}
Note that the Scala compiler can infer the type from the function call argument we pass in.
It’s not mandatory that we explicitly pass in the type argument.
Subtype Polymorphism
The key concept in subtype polymorphism is substitutability as defined in the Liskov
substitution principle. We can recognize a Scala function that exhibits subtype polymorphism
when at least one of its parameter types has subtypes — that is, when it’s a supertype of at
least one type.
This type relation is sometimes written as S <: T, which means S is a subtype of T or T :> S,
meaning T is a supertype of S. We sometimes call this inclusion polymorphism. Unlike
parametric polymorphism, we restrict the range of types a function can be applied to with this
subtype relationship.
In the following example, we make Circle and Square subtypes of Shape. The method
printArea() accepts a Shape but will also work correctly if any of the subtypes is passed to it:
trait Shape {
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 16
def getArea: Double
}
case class Square(side: Double) extends Shape {
override def getArea: Double = side * side
}
case class Circle(radius: Double) extends Shape {
override def getArea: Double = Math.PI * radius * radius
}
def printArea[T <: Shape](shape: T): Double = (math.floor(shape.getArea) * 100)/100
Let’s add a test to capture the expected behavior:
"Shapes" should "compute correct area" in {
val square = Square(10.0)
val circle = Circle(12.0)
assertResult(expected = 100.00)(printArea(square))
assertResult(expected = 452.39)(printArea(circle))
}
In the above example, the subtyping relation is written as T <: Shape, to mean that any
argument of type T can be safely used in a context where a term of type Shape is expected.
We constrain T to only variables that are subtypes of Shape. So, we say that function
printArea() is subtype polymorphic over subtypes of Shape.
Ad-Hoc Polymorphism
One of the easiest ways to think about ad-hoc polymorphism is in terms of a switch statement
that’s happening in the background but without a default case. In this case, the compiler
switches between different code implementations depending on the type of input a method
receives.
There’s a similarity between parametric and ad-hoc polymorphism: they both use generics to
allow code to work on different types. The main difference is that in the former, the same
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 17
code runs for every type. In the latter, possibly different logic is executed based on the type,
hence the switch-statement analogy in the previous paragraph.
There are three outstanding concepts required to understand ways Scala supports ad-hoc
polymorphism: function overloading, operator overloading, and implicits.
Function Overloading
Let’s look at a built-in example of where ad-hoc polymorphism is applied in Scala. Assume
we have a list of integers that we want to sort:
it should "sort integers correctly" in {
val intList = List(3,5,2,1,4)
val sortedIntList = intList.sorted
assertResult(expected = List(1,2,3,4,5))(actual = sortedIntList)
}
We just called the method sorted on the List, and it knew exactly how to sort integers since
they are a primitive type. What if we also want List to know how to sort another type that we
have, say student ID’s wrapped in a custom class:
case class StudentId(id: Int)
Much as the underlying type is an Int, the Scala compiler does not know how to sort the type
StudentId. Going by our switch-statement analogy, it has encountered a case without
implementation, and remember, we don’t have a default case.
As a matter of fact, let’s attempt to do that:
it should "sort custom types correctly" in {
val studentIds = List(StudentId(5), StudentId(1),StudentId(4), StudentId(3), StudentId(2))
val sortedStudentIds = studentIds.sorted
assertResult(
expected = List(
StudentId(1),
StudentId(2),
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 18
StudentId(3),
StudentId(4),
StudentId(5)
)
)(actual = sortedStudentIds)
}
This test will fail to compile with the following error:
No implicit arguments of type: Ordering[StudentId]
It so happens that the method sorted expects some help with sorting types it doesn’t know
about. The type Ordering is a trait whose job is very similar to Java’s Comparator interface,
in that it also declares a compareTo method that provides a sorting strategy for a type.
The idiomatic way to fix this error is to create an implicit class or value of type Ordering that
is within the scope of our code.
Since this is not an article about implicits, let’s fix the error by providing an implementation
of Ordering type for StudentId just within the test. We’ll do this by defining the ordering
strategy and passing it to the sorted method as an argument:
...
val ord: Ordering[StudentId] = (x, y) => x.id.compareTo(y.id)
val sortedStudentIds = studentIds.sorted(ord)
...
Operator Overloading
Operator overloading is not so different from function overloading. This is where different
operators have different implementations depending on the types of their arguments.
We know the semantics of common operators, especially the arithmetic ones like the addition
(+) and subtraction (-) operators. Operator overloading is the reason all the following
snippets of code compile and work:
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 19
val intSum = 1990 + 10
val dblSum = 13.37 + 15.81
val strConcat = "FirstName " + "LastName"
The addition operator is able to work for integers, doubles, and strings alike because it’s
overloaded for each of those types. The compiler can infer the right implementation of the
operator from the types of the operands.
We can take this same idea and overload existing Scala operators to take care of our unique
needs. Assuming we are building software to solve math problems, would we rather write our
operations like this:
a + b * c
Or:
Add(a, Multiply(b, c))
Both are equivalent, but the first one just looks more expressive and commonplace in the
mathematics domain. So, we can say operator overloading is just syntactic sugar to allow us
to program using notations that are closer to our target domain.
How Scala Supports Operator Overloading
In actual technical terms, operator overloading is really made possible by Scala’s
permissiveness with method names and flexibility in how we invoke methods on objects.
More specifically; Scala allows us to use some operator names in method naming. + and –
are valid method names for any class we create in Scala, unlike Java. Let’s create an
abstraction for handling complex numbers as a demo:
case class Complex(re: Double, im: Double) {
def + (op: Complex): Complex = Complex(re + op.re, imaginary + op.im)
def - (op: Complex): Complex = Complex(re - op.re, imaginary - op.im)
override def toString: String = s"$re + ${im}i"
}
191AIC302T-Object Oriented Programming with SCALA
Unit-III
Department of AI & DSPage 20
Notice that we can use operators as method names, which actually communicates our
intention more clearly, given the context. Secondly, there’s also flexibility in method
invocation syntax:
it should "add and subtract complex numbers successfully" in {
val cmpl1 = Complex(8.0, 3.0)
val cmpl2 = Complex(6.0, 2.0)
val cmplSum = cmpl1.+(cmpl2)
val cmplDiff = cmpl1 - cmpl2
assertResult(expected = "14.0 + 5.0i")(actual = cmplSum.toString)
assertResult(expected = "2.0 + 1.0i")(actual = cmplDiff.toString)
}
Notice that we can use postfix notation as in the addition invocation, but Scala also allows us
to separate the object, method name, and the argument as in the subtraction invocation where
we call (-) as an infix operator. Both are valid syntax in Scala.

More Related Content

Similar to Unit 3 notes.pdf

Class notes(week 6) on inheritance and multiple inheritance
Class notes(week 6) on inheritance and multiple inheritanceClass notes(week 6) on inheritance and multiple inheritance
Class notes(week 6) on inheritance and multiple inheritanceKuntal Bhowmick
 
Learn C# Programming - Classes & Inheritance
Learn C# Programming - Classes & InheritanceLearn C# Programming - Classes & Inheritance
Learn C# Programming - Classes & InheritanceEng Teong Cheah
 
The Scala Programming Language
The Scala Programming LanguageThe Scala Programming Language
The Scala Programming Languageleague
 
C++ programming introduction
C++ programming introductionC++ programming introduction
C++ programming introductionsandeep54552
 
Oop features java presentationshow
Oop features java presentationshowOop features java presentationshow
Oop features java presentationshowilias ahmed
 
Interview preparation for programming.pptx
Interview preparation for programming.pptxInterview preparation for programming.pptx
Interview preparation for programming.pptxBilalHussainShah5
 
Inheritance in Java beginner to advance with examples.pptx
Inheritance in Java beginner to advance with examples.pptxInheritance in Java beginner to advance with examples.pptx
Inheritance in Java beginner to advance with examples.pptxnaeemcse
 
Application package
Application packageApplication package
Application packageJAYAARC
 
C++ classes tutorials
C++ classes tutorialsC++ classes tutorials
C++ classes tutorialsakreyi
 
Bt8903, c# programming
Bt8903, c# programmingBt8903, c# programming
Bt8903, c# programmingsmumbahelp
 
Inheritance and interface
Inheritance and interfaceInheritance and interface
Inheritance and interfaceShubham Sharma
 

Similar to Unit 3 notes.pdf (20)

Class notes(week 6) on inheritance and multiple inheritance
Class notes(week 6) on inheritance and multiple inheritanceClass notes(week 6) on inheritance and multiple inheritance
Class notes(week 6) on inheritance and multiple inheritance
 
Learn C# Programming - Classes & Inheritance
Learn C# Programming - Classes & InheritanceLearn C# Programming - Classes & Inheritance
Learn C# Programming - Classes & Inheritance
 
Opp concept in c++
Opp concept in c++Opp concept in c++
Opp concept in c++
 
The Scala Programming Language
The Scala Programming LanguageThe Scala Programming Language
The Scala Programming Language
 
Unit 5.ppt
Unit 5.pptUnit 5.ppt
Unit 5.ppt
 
Unit 4 notes.pdf
Unit 4 notes.pdfUnit 4 notes.pdf
Unit 4 notes.pdf
 
C++ programming introduction
C++ programming introductionC++ programming introduction
C++ programming introduction
 
oops-1
oops-1oops-1
oops-1
 
Unit i
Unit iUnit i
Unit i
 
Oop features java presentationshow
Oop features java presentationshowOop features java presentationshow
Oop features java presentationshow
 
Interview preparation for programming.pptx
Interview preparation for programming.pptxInterview preparation for programming.pptx
Interview preparation for programming.pptx
 
Inheritance
InheritanceInheritance
Inheritance
 
Java sessionnotes
Java sessionnotesJava sessionnotes
Java sessionnotes
 
Inheritance in Java beginner to advance with examples.pptx
Inheritance in Java beginner to advance with examples.pptxInheritance in Java beginner to advance with examples.pptx
Inheritance in Java beginner to advance with examples.pptx
 
Oops
OopsOops
Oops
 
Application package
Application packageApplication package
Application package
 
C++ classes tutorials
C++ classes tutorialsC++ classes tutorials
C++ classes tutorials
 
Bt8903, c# programming
Bt8903, c# programmingBt8903, c# programming
Bt8903, c# programming
 
Inheritance and interface
Inheritance and interfaceInheritance and interface
Inheritance and interface
 
Only oop
Only oopOnly oop
Only oop
 

More from Revathiparamanathan (18)

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
 
Unit 5 notes.pdf
Unit 5 notes.pdfUnit 5 notes.pdf
Unit 5 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

Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
result management system report for college project
result management system report for college projectresult management system report for college project
result management system report for college projectTonystark477637
 
University management System project report..pdf
University management System project report..pdfUniversity management System project report..pdf
University management System project report..pdfKamal Acharya
 
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...ranjana rawat
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...Call Girls in Nagpur High Profile
 
UNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and workingUNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and workingrknatarajan
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...roncy bisnoi
 
Online banking management system project.pdf
Online banking management system project.pdfOnline banking management system project.pdf
Online banking management system project.pdfKamal Acharya
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingrakeshbaidya232001
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxAsutosh Ranjan
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsCall Girls in Nagpur High Profile
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCall Girls in Nagpur High Profile
 
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...ranjana rawat
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINESIVASHANKAR N
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordAsst.prof M.Gokilavani
 
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSMANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSSIVASHANKAR N
 
Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)simmis5
 

Recently uploaded (20)

Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur EscortsCall Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
Call Girls Service Nagpur Tanvi Call 7001035870 Meet With Nagpur Escorts
 
result management system report for college project
result management system report for college projectresult management system report for college project
result management system report for college project
 
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
(INDIRA) Call Girl Aurangabad Call Now 8617697112 Aurangabad Escorts 24x7
 
University management System project report..pdf
University management System project report..pdfUniversity management System project report..pdf
University management System project report..pdf
 
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
The Most Attractive Pune Call Girls Manchar 8250192130 Will You Miss This Cha...
 
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...Booking open Available Pune Call Girls Pargaon  6297143586 Call Hot Indian Gi...
Booking open Available Pune Call Girls Pargaon 6297143586 Call Hot Indian Gi...
 
UNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and workingUNIT-V FMM.HYDRAULIC TURBINE - Construction and working
UNIT-V FMM.HYDRAULIC TURBINE - Construction and working
 
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service NashikCall Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
Call Girls Service Nashik Vaishnavi 7001305949 Independent Escort Service Nashik
 
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
Call Girls Pimpri Chinchwad Call Me 7737669865 Budget Friendly No Advance Boo...
 
Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024Water Industry Process Automation & Control Monthly - April 2024
Water Industry Process Automation & Control Monthly - April 2024
 
Online banking management system project.pdf
Online banking management system project.pdfOnline banking management system project.pdf
Online banking management system project.pdf
 
Porous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writingPorous Ceramics seminar and technical writing
Porous Ceramics seminar and technical writing
 
Coefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptxCoefficient of Thermal Expansion and their Importance.pptx
Coefficient of Thermal Expansion and their Importance.pptx
 
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur EscortsHigh Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
High Profile Call Girls Nagpur Meera Call 7001035870 Meet With Nagpur Escorts
 
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service NashikCollege Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
College Call Girls Nashik Nehal 7001305949 Independent Escort Service Nashik
 
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
The Most Attractive Pune Call Girls Budhwar Peth 8250192130 Will You Miss Thi...
 
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINEMANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
MANUFACTURING PROCESS-II UNIT-2 LATHE MACHINE
 
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete RecordCCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
CCS335 _ Neural Networks and Deep Learning Laboratory_Lab Complete Record
 
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLSMANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
MANUFACTURING PROCESS-II UNIT-5 NC MACHINE TOOLS
 
Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)Java Programming :Event Handling(Types of Events)
Java Programming :Event Handling(Types of Events)
 

Unit 3 notes.pdf

  • 1. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 1 Inheritance and Polymorphism Inheritance: Defining derived classes & Visibility modes – Types of Inheritance: Single- level Inheritance - Multilevel Inheritance - Multiple Inheritance - Hierarchical Inheritance - Hybrid Inheritance – Inheritance vs Composition – Polymorphism: Types of Polymorphism - Parametric Polymorphism - Subtype Polymorphism - Ad-Hoc Polymorphism - Function Overloading - Operator Overloading. Inheritance: Inheritance in Scala is the concept of inheriting values and properties by one object from another object. Scala programming language is a programming language that integrates features of both object- oriented programming and function programming supports inheritance too, as it is a really important feature of OOP's concept. Before going ahead, let's see some key terms related to inheritance in Scala,  Super Class is also known as base class or parent class. It is the class whose features are inherited by other classes.  Sub Class is also known as child class, derived class, or extended class. It is the class that inherits features from other classes. To implement the concepts of inheritance we need to understand the working of some keywords in Scala:  extends: The extends keyword in Scala is used to inherit features of one class by another class. baseClass extends parentClass This extends keyword is used to inherit class while creating a new one.  With: the with keyword in Scala is used when we need to inherit more than one class by another class. Syntax class SubClassName extends SuperClassName(){ /* Write your code * methods and fields etc. */ }
  • 2. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 2 Types of Inheritances in Scala While inheriting classes in Scala, there can be multiple ways to inherit classes. Here are types of inheritance in Scala: 1. Single Inheritance 2. Multiple Inheritance 3. Multilevel Inheritance 4. Hierarchical Inheritance 5. Hybrid Inheritance 1. Single Inheritance
  • 3. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 3  Single inheritance is a type of inheritance in which one class is inherited by another class.  The concept is depicted in the following diagram, Here, in single inheritance, one class is simply inherited by another class in Scala. Example: class class1{ var value1 = 935 } class class2 extends class1{ val value2 = 54 def printValues(){ println("Value 1: " + value1 ) println("Value 2: " + value2 ) println("Sum: " + (value1 + value2)) } } object MyClass { def main(args: Array[String]) { val object1 = new class2(); object1.printValues() } } Multiple Inheritance Multiple inheritance is a type of inheritance in which multiple classes are inherited by one class at a time.
  • 4. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 4 Example: trait baseClass1{ var value1 = 935 } trait baseClass2{ var value2 = 43 } class derivedClass extends baseClass1 with baseClass2{ def printValues(){ println("Derived Class") println("Value 1 : " + value1 ) println("Value 2 : " + value2 ) println("Concatination : " + (value1 + value2) ) } } object MyClass { def main(args: Array[String]) { val object1 = new derivedClass();
  • 5. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 5 object1.printValues() } } Multilevel Inheritance  Multi-Level inheritance is a type of inheritance in which one class is inherited by another class which is in turn inherited by the third class.  The concept is depicted in the following diagram, Example: class class1{ var value1 = 935 } class class2 extends class1{ val value2 = 54 } class class3 extends class2{
  • 6. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 6 def printValues(){ println("Value 1: " + value1 ) println("Value 2: " + value2 ) println("Sum: " + (value1 + value2)) } } object MyClass { def main(args: Array[String]) { val object1 = new class3(); object1.printValues() } } Hierarchical Inheritance  Hierarchical inheritance is a type of inheritance in which one class is inherited by more than one class.  The concept is depicted in the following diagram, Example: class baseClass{
  • 7. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 7 var value1 = 935 } class derivedClass1 extends baseClass{ def printValues(){ println("nDerived Class 1") val value2 = 54 println("Value 1: " + value1) println("Value 2: " + value2) println("Sum: " + (value1 + value2)) } } class derivedClass2 extends baseClass{ def printValues(){ val value2 = 341 println("nDerived Class 2") println("Value 1 : " + value1 ) println("Value 2 : " + value2 ) println("Concatination : " + value1 + value2 ) } } object MyClass { def main(args: Array[String]) {
  • 8. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 8 val object1 = new derivedClass1(); object1.printValues() val object2 = new derivedClass2(); object2.printValues() } } Hybrid Inheritance  Hybrid Inheritance is a special type of inheritance which is a combination of hierarchical and multiple inheritance in Scala. class A { var numA: Int = 0; def setA(n: Int) { numA = n; } def printA() { printf("numA: %dn", numA); } } class B extends A { var numB: Int = 0; def setB(n: Int) { numB = n; } def printB() { printf("numB: %dn", numB); } } class C extends B { var numC: Int = 0; def setC(n: Int) { numC = n;
  • 9. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 9 } def printC() { printf("numC: %dn", numC); } } class D extends A { var numD: Int = 0; def setD(n: Int) { numD = n; } def printD() { printf("numD: %dn", numD); } } object Sample { def main(args: Array[String]) { var obj1 = new C(); var obj2 = new D(); obj1.setA(10); obj1.setB(20); obj1.setC(30); obj1.printA(); obj1.printB(); obj1.printC(); obj2.setA(40); obj2.setD(50); obj2.printA(); obj2.printD(); } } Inheritance vs Composition: Composition and inheritance are two ways to define a new class in terms of another existing class. If what you're after is primarily code reuse, you should in general prefer composition to inheritance. Only inheritance suffers from the fragile base class problem, in which you can inadvertently break subclasses by changing a superclass.
  • 10. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 10 One question you can ask yourself about an inheritance relationship is whether it models an is-a relationship.[8] For example, it would be reasonable to say that ArrayElement is-an Element. Another question you can ask is whether clients will want to use the subclass type as a superclass type.[9] In the case of ArrayElement, we do indeed expect clients will want to use an ArrayElement as an Element. If you ask these questions about the inheritance relationships shown in Figure 10.3, do any of the relationships seem suspicious? In particular, does it seem obvious to you that a LineElement is-an ArrayElement? Do you think clients would ever need to use a LineElement as an ArrayElement? In fact, we defined LineElement as a subclass of ArrayElement primarily to reuse ArrayElement's definition of contents. Perhaps it would be better, therefore, to define LineElement as a direct subclass of Element, like this: class LineElement(s: String) extends Element { val contents = Array(s) override def width = s.length override def height = 1 } What is Inheritance? Inheritance is one of the most powerful tools in implementing code reusability in object- oriented programming. It refers to the functionality by which one object acquires the characteristics of one or more other objects. Inheritance in C++ means you can create classes that derive their attributes from existing classes. This means you specialize a class to create an is-a relationship between the classes which results in a strong coupling between the base and derived classes. Implementing inheritance promotes code reusability because new classes are created from existing classes. Class inheritance also makes it easier to modify the implementation being reused. But class inheritance has some downsides to it too. First, because inheritance is defined at compile-time, you cannot change the implementations inherited from parent classes at run-time. What is Composition? OOP provides yet another relationship between classes called composition, which is also known as a has-a relationship. If the features of one object need to be a part of another object, the relationship calls for composition. To compose a class from existing classes, an object of each class should be declared as the member of the new class. In simple words, using an object within another object is known as composition. Many a times, you might want to use an object as a field within another class. You use an object inside a class in composition. Unlike class
  • 11. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 11 inheritance, object composition is defined dynamically at run-time through objects acquiring references to other objects. Additionally, composition provides a better way to use an object without compromising the internal details of the object, that is where composition is useful. Difference between Composition and Inheritance Approach While both inheritance and composition promote code reusability in object oriented system by establishing relationships between classes and they provide equivalent functionality in many ways, they use different approaches. With inheritance, you can create classes that derive their attributes from existing classes so while using inheritance to create a class, you can expand on an existing class. On the contrary, using an object within another object is known as composition. Object composition is an alternative to class inheritance. If the features of one object need to be a part of another object, the relationship calls for composition. Relationship In inheritance, you specialize a class to create an “is-a” relationship between the classes which results in a strong coupling between the base and derived classes. It enables a hierarchy of classes to be designed and the hierarchy begins with the most general class and moves to more specific classes. By implementing inheritance, member functions from one class become properties of another class without coding them explicitly within the class. In composition, you use an object inside a class and any requests to the object are forwarded to the object. The internal details are not exposed to each other in composition, so it is a “has-a” relationship. Implementation Class inheritance is defined at compile-time, so you cannot change the implementations inherited from parent classes at run-time. Because inheritance exposes a subclass to details of its parent’s implementation, it often breaks encapsulation. Any changes in the parent class will reflect in the subclass which can create problems when you try to reuse a subclass. Object composition, on the contrary, is defined dynamically at run-time through objects acquiring references to other objects. And because objects are accessed solely through their interfaces, it won’t break encapsulation. Any object can be replaced at run-time by another object as long as it has the same type.
  • 12. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 12 Polymorphism  In the simplest of terms, polymorphism means one object having many forms or an object’s ability to exhibit multiple behaviors. In computer terms, this would show up as handling different data types using the same interface or method.  The more formal definition is: polymorphism is the provision of a single interface to entities of different types or the use of a single symbol to represent multiple different types.  Polymorphism means that a function type comes "in many forms".  In programming it means that the function can be applied to arguments of many types, or the type can have instances of many types. Consider the following class hierarchy:
  • 13. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 13 Example: trait Animal { def fitness: Int } trait Reptile extends Animal trait Mammal extends Animal trait Zebra extends Mammal { def zebraCount: Int } trait Giraffe extends Mammal Parametric Polymorphism If we’re to take only one statement from this section, it’s that parametric polymorphism is just generics as used in languages such as Java, C#, and Scala. We can easily recognize parametrically polymorphic functions in Scala by the presence of one or more type parameters delimited by square brackets in the method signature — they enable us to apply the same logic to different data types. Let’s look at an example to illustrate this. Imagine we’re writing a method to pair-wise reverse a List. We want to be able to input List(1,2,3,4,5,6) and get output List(2,1,4,3,6,5). If the length is odd, then the last element should stay in its place such that List(1,2,3,4,5) becomes List(2,1,4,3,5). The Naive Solution
  • 14. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 14 def pairWiseReverseInt(xs: List[Int]): List[Int] = xs.grouped(2).flatMap(_.reverse).toList Let’s create a test for the above scenario: it should "reverse an even length int list" in { val input = List(1,2,3,4,5,6) val expected = List(2,1,4,3,5,6) val actual = pairWiseReverseInt(input) assert(actual == expected) } The method we’ve written works well for integer arrays but is not reusable for other types. As an example, if we’d like to pair-wise reverse a list of strings or doubles, we’d have to create additional methods and pointlessly duplicate the logic: def pairWiseReverseString(xs: List[String]): List[String] = arr.grouped(2).flatMap(_.reverse).toList it should "pair-wise reverse a string list" in { val original = List("a","b","c","d","e") val expected = List("b","a","d","c","e") val actual = pairWiseReverseString(original) assertResult(expected)(actual) } The DRY Solution Parametric polymorphism helps us eliminate this unnecessary duplication of code by introducing a second formal parameter list for type parameters. With parametric polymorphism, the logic remains the same for all the different types. To illustrate, we’ll refactor the above pair-wise reverse methods into one that works for all types: def pairWiseReverse[A](xs:List[A]): List[A] = xs.grouped(2).flatMap(_.reverse).toList We’ve represented the type parameter by letter A, but we could just as well have used K, T, or any other letter — it doesn’t matter. As with all formal parameters, we expect to substitute
  • 15. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 15 A during a method call with a concrete type such as Int, String, or any other concrete type in our case: it should "pair-wise reverse lists of any type" in { val originalInts = List(1,2,3,4,5) val expectedInts = List(2,1,4,3,5) val originalStrings = List("a","b","c","d","e") val expectedStrings = List("b","a","d","c","e") val originalDoubles = List(1.2,2.7,3.4,4.3,5.0) val expectedDoubles = List(2.7,1.2,4.3,3.4,5.0) assertResult(expectedInts)(pairWiseReverse[Int](originalInts)) assertResult(expectedStrings)(pairWiseReverse[String](originalStrings)) assertResult(expectedDoubles)(pairWiseReverse[Double](originalDoubles)) } Note that the Scala compiler can infer the type from the function call argument we pass in. It’s not mandatory that we explicitly pass in the type argument. Subtype Polymorphism The key concept in subtype polymorphism is substitutability as defined in the Liskov substitution principle. We can recognize a Scala function that exhibits subtype polymorphism when at least one of its parameter types has subtypes — that is, when it’s a supertype of at least one type. This type relation is sometimes written as S <: T, which means S is a subtype of T or T :> S, meaning T is a supertype of S. We sometimes call this inclusion polymorphism. Unlike parametric polymorphism, we restrict the range of types a function can be applied to with this subtype relationship. In the following example, we make Circle and Square subtypes of Shape. The method printArea() accepts a Shape but will also work correctly if any of the subtypes is passed to it: trait Shape {
  • 16. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 16 def getArea: Double } case class Square(side: Double) extends Shape { override def getArea: Double = side * side } case class Circle(radius: Double) extends Shape { override def getArea: Double = Math.PI * radius * radius } def printArea[T <: Shape](shape: T): Double = (math.floor(shape.getArea) * 100)/100 Let’s add a test to capture the expected behavior: "Shapes" should "compute correct area" in { val square = Square(10.0) val circle = Circle(12.0) assertResult(expected = 100.00)(printArea(square)) assertResult(expected = 452.39)(printArea(circle)) } In the above example, the subtyping relation is written as T <: Shape, to mean that any argument of type T can be safely used in a context where a term of type Shape is expected. We constrain T to only variables that are subtypes of Shape. So, we say that function printArea() is subtype polymorphic over subtypes of Shape. Ad-Hoc Polymorphism One of the easiest ways to think about ad-hoc polymorphism is in terms of a switch statement that’s happening in the background but without a default case. In this case, the compiler switches between different code implementations depending on the type of input a method receives. There’s a similarity between parametric and ad-hoc polymorphism: they both use generics to allow code to work on different types. The main difference is that in the former, the same
  • 17. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 17 code runs for every type. In the latter, possibly different logic is executed based on the type, hence the switch-statement analogy in the previous paragraph. There are three outstanding concepts required to understand ways Scala supports ad-hoc polymorphism: function overloading, operator overloading, and implicits. Function Overloading Let’s look at a built-in example of where ad-hoc polymorphism is applied in Scala. Assume we have a list of integers that we want to sort: it should "sort integers correctly" in { val intList = List(3,5,2,1,4) val sortedIntList = intList.sorted assertResult(expected = List(1,2,3,4,5))(actual = sortedIntList) } We just called the method sorted on the List, and it knew exactly how to sort integers since they are a primitive type. What if we also want List to know how to sort another type that we have, say student ID’s wrapped in a custom class: case class StudentId(id: Int) Much as the underlying type is an Int, the Scala compiler does not know how to sort the type StudentId. Going by our switch-statement analogy, it has encountered a case without implementation, and remember, we don’t have a default case. As a matter of fact, let’s attempt to do that: it should "sort custom types correctly" in { val studentIds = List(StudentId(5), StudentId(1),StudentId(4), StudentId(3), StudentId(2)) val sortedStudentIds = studentIds.sorted assertResult( expected = List( StudentId(1), StudentId(2),
  • 18. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 18 StudentId(3), StudentId(4), StudentId(5) ) )(actual = sortedStudentIds) } This test will fail to compile with the following error: No implicit arguments of type: Ordering[StudentId] It so happens that the method sorted expects some help with sorting types it doesn’t know about. The type Ordering is a trait whose job is very similar to Java’s Comparator interface, in that it also declares a compareTo method that provides a sorting strategy for a type. The idiomatic way to fix this error is to create an implicit class or value of type Ordering that is within the scope of our code. Since this is not an article about implicits, let’s fix the error by providing an implementation of Ordering type for StudentId just within the test. We’ll do this by defining the ordering strategy and passing it to the sorted method as an argument: ... val ord: Ordering[StudentId] = (x, y) => x.id.compareTo(y.id) val sortedStudentIds = studentIds.sorted(ord) ... Operator Overloading Operator overloading is not so different from function overloading. This is where different operators have different implementations depending on the types of their arguments. We know the semantics of common operators, especially the arithmetic ones like the addition (+) and subtraction (-) operators. Operator overloading is the reason all the following snippets of code compile and work:
  • 19. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 19 val intSum = 1990 + 10 val dblSum = 13.37 + 15.81 val strConcat = "FirstName " + "LastName" The addition operator is able to work for integers, doubles, and strings alike because it’s overloaded for each of those types. The compiler can infer the right implementation of the operator from the types of the operands. We can take this same idea and overload existing Scala operators to take care of our unique needs. Assuming we are building software to solve math problems, would we rather write our operations like this: a + b * c Or: Add(a, Multiply(b, c)) Both are equivalent, but the first one just looks more expressive and commonplace in the mathematics domain. So, we can say operator overloading is just syntactic sugar to allow us to program using notations that are closer to our target domain. How Scala Supports Operator Overloading In actual technical terms, operator overloading is really made possible by Scala’s permissiveness with method names and flexibility in how we invoke methods on objects. More specifically; Scala allows us to use some operator names in method naming. + and – are valid method names for any class we create in Scala, unlike Java. Let’s create an abstraction for handling complex numbers as a demo: case class Complex(re: Double, im: Double) { def + (op: Complex): Complex = Complex(re + op.re, imaginary + op.im) def - (op: Complex): Complex = Complex(re - op.re, imaginary - op.im) override def toString: String = s"$re + ${im}i" }
  • 20. 191AIC302T-Object Oriented Programming with SCALA Unit-III Department of AI & DSPage 20 Notice that we can use operators as method names, which actually communicates our intention more clearly, given the context. Secondly, there’s also flexibility in method invocation syntax: it should "add and subtract complex numbers successfully" in { val cmpl1 = Complex(8.0, 3.0) val cmpl2 = Complex(6.0, 2.0) val cmplSum = cmpl1.+(cmpl2) val cmplDiff = cmpl1 - cmpl2 assertResult(expected = "14.0 + 5.0i")(actual = cmplSum.toString) assertResult(expected = "2.0 + 1.0i")(actual = cmplDiff.toString) } Notice that we can use postfix notation as in the addition invocation, but Scala also allows us to separate the object, method name, and the argument as in the subtraction invocation where we call (-) as an infix operator. Both are valid syntax in Scala.