This blog is in the continuation of its first part where we discussed the basic part of object-oriented concepts. In this blog, we will cover four pillars in the object-oriented world of programming in Scala.
OOPS Four Pillars
Four pillars are basically the software design principles that help you to write clean Object-Oriented Code and these are:
- Abstraction
- Encapsulation
- Inheritance
- Polymorphism
Let’s take a closer look at each of them.
Abstraction in Object Oriented Programming
Abstraction is basically only showing the necessary details to the user of the object. For instance, when you turn on your laptop you just push the power button and the screen of your laptop lit up you don’t care about the inner mechanism of what’s going on and that’s what abstraction is.
The best part of Abstraction is you decouple the user from the underlying implementation. Let’s take a coding example:
Suppose you are making an app that classifies different shapes and calculates their area. So abstraction in your app will be just the area of your desired shapes you don’t have to worry about underlining implementation of how the area is been calculated.
package OOPs
object Main extends App{
val shape = new Shapes
println("Area of circle: " + shape.circle(4))
val polygon = new TwoDShapes
println("Area of equilateral triangle: " + polygon.triangle(2, 2))
println(polygon.circle(4))
println(polygon.square(5))
}
Encapsulation in Object Oriented Programming
It is basically binding together fields and methods that manipulate your data and that keep both safes from outside interference and misuse.
This can be done using keywords like private and protected in Scala.
Encapsulation Example
package OOPs
trait ThreeDSpheres {
private val pi = 3.1416
def cylinder(h: Int, r: Int): Double = 2 * pi * r * (h + r) //cylinder area
}
Inheritance in Object Oriented Programming
It is the most powerful feature and it basically allows you to have code reusability.
As an example, consider the case where you have an existing class and you want to build a new class that uses the previous class’s stuff, but adds additional features.
Classes that are derived from existing classes are either called subclass or child classes and the class from which that subclass can be derived is called superclass or parent class.
Inheritance Example
Taking the same area of shape example suppose you have two classes one is of Shapes which is implementing area of normal shapes and you have another class which implements the area of 3-D shapes now you can use some methods from Shapes class in order to calculate the area of 3-D shapes
package OOPs
class Shapes {
private val pi = 3.1416
def rectangle(a: Int, b: Int): Int = a * b
def square(a: Int): Int = a * a
def trapezium(a:Int, b: Int, h: Int): Double = 0.5 * (a + b) * h
def triangle(h: Int, b: Int): Double = 0.5 * h * b
def circle(r: Int): Double = pi * r * r
}
package OOPs
class ThreeDShapes extends Shapes with ThreeDSpheres {
private val pi = 3.1416
override def square(a: Int): Int = 6 * a * a //cube
override def trapezium(a: Int, b: Int, h: Int): Double = 2 * h * (a + b) //csa Cuboid
override def circle(r: Int): Double = 2 * r //diameter
override def cylinder(h: Int, r: Int): Double = pi * h * r * r //cylinder volume
def cone(slantHeight: Int, r: Int): Double = pi * r * slantHeight //sa of cone
}
Polymorphism in Object Oriented Programming
Polymorphism is basically the combination of two words “Poly” which means Many and “Morph” which means Forms, yeah I know it sounds a little confusing so basically, it allows you to determine what kind of function to run while the program is running.
In Scala we can divide Polymorphism into the following types:
Parametric Polymorphism
It allows us to apply the same logic to different data types just like generics.
def pairReversing[Z](xs:List[Z]): List[Z] = xs.grouped(2).flatMap(_.reverse).toList
Subtype Polymorphism
A Scala function is said to be subtype polymorphism if at least one of its parameter types has subtypes based on the Liskov substitution principle.
This type of polymorphism is written as S <: T, which means S is a subtype of T or T :> S, meaning T is a supertype of S.
Example
trait Shape {
def getArea: Double
}
case class Cube(side: Double) extends Shape {
override def getVolume: Double = side * side * side
}
case class Cone(radius: Double, height: Double) extends Shape {
private val pi = 3.124
override def getVolume: Double = 0.333 * radius * radius * height
}
def printArea[T <: Shape](shape: T): Double = (math.floor(shape.getVolume) * 100)/100
Conclusion
Thank you for making it to the end of this blog on OOP I hope you got a basic understanding of the four pillars of object-oriented programming.
Reference
In order to get more coding examples related to the four pillars you can refer to the following link:
https://docs.scala-lang.org/overviews/scala-book/oop-pizza-example.html
