In object-oriented programming, a class is a blueprint for creating objects. Classes encapsulate data (properties) and behaviors (methods) that define the objects created from the class. This encapsulation promotes modularity, making your code easier to maintain and understand.

Defining a Class

Defining a class in Swift is straightforward. You use the class keyword followed by the class name and a pair of curly braces {}. Here’s a simple example:

class Person {
    // Properties
    var name: String
    var age: Int

    // Initializer
    init(name: String, age: Int) {
        self.name = name
        self.age = age
    }

    // Method
    func greet() {
        print("Hello, my name is \(name) and I am \(age) years old.")
    }
}

In this example:

  • Person is the name of the class.
  • name and age are properties of the class.
  • The init method is an initializer that sets up the initial state of the object.
  • The greet method defines a behavior of the class.

Class Properties and Methods

Properties

Properties are variables or constants that belong to a class. They store values associated with each instance of the class.

  • Stored Properties: These store values persistently.
  • Computed Properties: These calculate values dynamically.

Example of stored and computed properties:

class Circle {
    var radius: Double

    init(radius: Double) {
        self.radius = radius
    }

    var circumference: Double {
        return 2 * .pi * radius
    }
}

Methods

Methods are functions that belong to a class. They define the behaviors of the objects created from the class.

Example of a method:

class Rectangle {
    var width: Double
    var height: Double

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

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

Initializers

Initializers are special methods that set up the initial state of an object. The most common initializer is the init method.

class Vehicle {
    var brand: String
    var year: Int

    init(brand: String, year: Int) {
        self.brand = brand
        self.year = year
    }
}

Swift also supports convenience initializers, which call another initializer from the same class to handle part of the initialization process.

class Vehicle {
    var brand: String
    var year: Int

    init(brand: String, year: Int) {
        self.brand = brand
        self.year = year
    }

    convenience init() {
        self.init(brand: "Unknown", year: 0)
    }
}

Inheritance

Inheritance allows a class to inherit properties and methods from another class. This promotes code reuse and establishes a hierarchy between classes.

class Animal {
    var name: String

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

    func makeSound() {
        print("\(name) makes a sound")
    }
}

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

In this example, Dog inherits from Animal and overrides the makeSound method to provide its own implementation.

Class vs. Struct

Both classes and structs can define properties and methods, but they have key differences:

  • Classes:
    • Reference types (objects are shared)
    • Support inheritance
    • Can use type casting to check and interpret the type of a class instance at runtime
  • Structs:
    • Value types (objects are copied)
    • Do not support inheritance
    • Used for lightweight data structures
struct Point {
    var x: Int
    var y: Int
}

var point1 = Point(x: 0, y: 0)
var point2 = point1
point2.x = 10

print(point1.x) // Output: 0
print(point2.x) // Output: 10

Practical Examples

Let’s see a practical example that combines several of the concepts we’ve discussed.

class BankAccount {
    var accountNumber: String
    var balance: Double

    init(accountNumber: String, initialBalance: Double) {
        self.accountNumber = accountNumber
        self.balance = initialBalance
    }

    func deposit(amount: Double) {
        balance += amount
        print("Deposited \(amount). New balance is \(balance).")
    }

    func withdraw(amount: Double) {
        if amount <= balance {
            balance -= amount
            print("Withdrew \(amount). New balance is \(balance).")
        } else {
            print("Insufficient funds.")
        }
    }
}

let account = BankAccount(accountNumber: "123456", initialBalance: 500.0)
account.deposit(amount: 150.0)
account.withdraw(amount: 200.0)

Conclusion

Classes are a cornerstone of object-oriented programming in Swift, providing a robust way to structure code. They allow you to create complex, reusable, and maintainable applications by encapsulating data and behaviors. Understanding classes, properties, methods, initializers, and inheritance will greatly enhance your Swift programming skills.

By mastering these concepts, you’ll be well-equipped to tackle a wide range of programming challenges in Swift, making your apps more efficient, readable, and scalable. Happy coding!