Object Oriented Programming(OOP)

Object-Oriented Programming (OOP) is a programming paradigm based on the concept of objects which can contain data (properties) and code (methods). Swift, as a modern programming language, fully supports OOP principles, including encapsulation, inheritance, polymorphism and abstraction.

Core Principles of OOP

  1. Encapsulation
  2. Inheritance
  3. Polymorphism
  4. Abstraction

Encapsulation

  • Binding data (properties) and behaviors (methods) within a class or struct.
  • Restricting access to internal implementation using access control (private, fileprivate, etc.).
class Person {
    private var name: String

    init(name: String) {
        self.name = name
    }

    func getName() -> String {
        return name
    }
}

let person = Person(name: "User")
print(person.getName())  // Output: User

Inheritance

  • Creating a new class that inherits properties and methods from an existing class.
  • The superclass provides the base functionality, while the subclass can override or extend it.
class User {
    func name() {
        print("My Name is Bishal")
    }
}

class Department: User {
    override func name() {
        print("My Name is Elon")
    }
}

let dept = Department()
dept.name()  // Output: My Name is Elon

1.Single Inheritance

In Swift, a subclass can inherit from only one superclass. This is the default type of inheritance in Swift.

class Animal {
    func eat() {
        print("Animal is eating")
    }
}

class Dog: Animal {
    func bark() {
        print("Dog is barking")
    }
}

let dog = Dog()
dog.eat()  // Inherited from Animal
dog.bark() // Specific to Dog

//OutPut:
Animal is eating
Dog is barking

2.Multilevel Inheritance

Multilevel inheritance refers to a chain of inheritance where a class inherits from a subclass of another class.

class Animal {
    func breathe() {
        print("Breathing...")
    }
}

class Mammal: Animal {
    func walk() {
        print("Walking...")
    }
}

class Human: Mammal {
    func speak() {
        print("Speaking...")
    }
}

let human = Human()
human.breathe() // From Animal
human.walk()    // From Mammal
human.speak()   // Specific to Human

3.Hierarchical Inheritance

In hierarchical inheritance, multiple subclasses inherit from a single superclass.

class Shape {
    func area() {
        print("Calculating area")
    }
}

class Circle: Shape {
    func radius() {
        print("Radius of the circle")
    }
}

class Rectangle: Shape {
    func dimensions() {
        print("Dimensions of the rectangle")
    }
}

let circle = Circle()
circle.area()    // Inherited from Shape
circle.radius()  // Specific to Circle

let rectangle = Rectangle()
rectangle.area()      // Inherited from Shape
rectangle.dimensions() // Specific to Rectangle

4.Multiple Inheritance

Swift does not allow direct multiple inheritance (a class inheriting from more than one class). However, it supports multiple inheritance using protocols. A class or struct can conform to multiple protocols to achieve the desired behaviour.

protocol Flyable {
    func fly()
}

protocol Swimmable {
    func swim()
}

class Duck: Flyable, Swimmable {
    func fly() {
        print("Duck is flying")
    }

    func swim() {
        print("Duck is swimming")
    }
}

let duck = Duck()
duck.fly()
duck.swim()

5.Hybrid Inheritance

Swift allows combining inheritance, protocols, and composition to achieve hybrid inheritance patterns.

protocol Sound {
    func makeSound()
}

class Animal {
    func eat() {
        print("Animal is eating")
    }
}

class Dog: Animal, Sound {
    func makeSound() {
        print("Dog is barking")
    }
}

class Bird: Animal, Sound {
    func makeSound() {
        print("Bird is chirping")
    }
}

let dog = Dog()
dog.eat()
dog.makeSound()

let bird = Bird()
bird.eat()
bird.makeSound()

Combination with Protocol Oriented Programming

In Swift, protocol-oriented programming complements inheritance by encouraging the use of protocols for shared behaviour.

protocol Drivable {
    func drive()
}

protocol Flyable {
    func fly()
}

class Car: Drivable {
    func drive() {
        print("Car is driving")
    }
}

class Airplane: Flyable, Drivable {
    func fly() {
        print("Airplane is flying")
    }

    func drive() {
        print("Airplane is taxiing on the runway")
    }
}

let car = Car()
car.drive()

let airplane = Airplane()
airplane.drive()
airplane.fly()

Polymorphism

  • Allowing objects to be treated as instances of their parent class.
  • Achieved through method overriding and protocol conformance.
class Animal {
    func getName() {
        print("Animal name")
    }
}

class Cat: Animal {
    override func getName() {
        print("Cat")
    }
}

class Dog: Animal {
    override func getName() {
        print("Dog")
    }
}

let animals: [Animal] = [Cat(), Dog()]
for animal in animals {
    animal.makeSound()
}
// Output:
// Cat
// Dog

Types of Polymorphism

  1. Compile-Time Polymorphism (Method Overloading)
    • Swift allows multiple methods with the same name but different parameters in the same scope. This is called method overloading.
class Math {
    func add(a: Int, b: Int) -> Int {
        return a + b
    }

    func add(a: Double, b: Double) -> Double {
        return a + b
    }

    func add(a: Int, b: Int, c: Int) -> Int {
        return a + b + c
    }
}

let math = Math()
print(math.add(a: 2, b: 3))        // Output: 5
print(math.add(a: 2.5, b: 3.5))    // Output: 6.0
print(math.add(a: 1, b: 2, c: 3))  // Output: 6

2.Run-Time Polymorphism (Method Overriding)

  • In run-time polymorphism, a subclass can override a method in its superclass to provide a specific implementation.
class Animal {
    func makeSound() {
        print("Animal makes a sound")
    }
}

class Dog: Animal {
    override func makeSound() {
        print("Dog barks")
    }
}

class Cat: Animal {
    override func makeSound() {
        print("Cat meows")
    }
}

let animals: [Animal] = [Dog(), Cat(), Animal()]
for animal in animals {
    animal.makeSound()
}
// Output:
// Dog barks
// Cat meows
// Animal makes a sound

Abstraction

  • Hiding implementation details while exposing essential features through protocols or abstract classes.
  • Achieved in Swift using protocols.
protocol Shape {
    func area() -> Double
}

class Circle: Shape {
    var radius: Double
    init(radius: Double) {
        self.radius = radius
    }

    func area() -> Double {
        return 3.14 * radius * radius
    }
}

class Rectangle: Shape {
    var width: Double
    var height: Double

    init(width: Double, height: Double) {
        self.width = width
        self.height = height
    }

    func area() -> Double {
        return width * height
    }
}

let shapes: [Shape] = [Circle(radius: 5), Rectangle(width: 4, height: 6)]
for shape in shapes {
    print(shape.area())
}
// Output:
// 78.5
// 24.0

Leave a Reply

Your email address will not be published. Required fields are marked *