Object Oriented Programming in Swift

Become a Subscriber

Swift is such an amazing language. The standard library supports both Functional and Object Oriented programming paradigms. For many developers, OOP has been the core knowledge base for which we learned to program. Classes, abstraction and scope are something OOP programmers think about constantly. Regardless of your preferred approach, it is important to understand both functional and OOP paradigms as well as some of the common programming patterns. Third-party libraries may favor one or the other, requiring you to understand the syntax of such, and some aspects of programming are clearly suited for one or the other.

Constructs that are mostly Object Oriented

Most internal constructs in the swift standard library can be divided into “better for OOP” or “best for functional” with a few being equally suitable for both. These are the constructs that are best used for object-oriented programming:

Classes

In Swift a class behaves as they would in many other languages:

  • They have states such as instance, singleton, initializers, de-initializers
  • Properties with various access like private and public
  • Inheritance. Swift supports multiple inheritance, often lacking in C-derived languages
  • Type casting and validation

Classes in Swift are passed by reference, meaning that each time a class is initialized, an instance of it is stored in memory and subsequent updates and fetches to the instance are done through memory pointers. Classes are crucial for singleton and factory patterns among others.

Protocols

Swift calls them Protocols, but many developers may call them Interfaces. They are basically like the Interfaces you would see in many other languages, with a bit of additional functionality. Protocols allow you to define properties and methods separately from Classes, giving you the ability to inherit from multiple rule sets that these Protocols define. Overall Protocols help you to write more rigid code, which is especially helpful when making libraries that other developers may use or when dealing with class abstraction.

Mutability

Put simply, mutability is the ability to modify the value and/or type of a variable once initially defined. Swift encourages developers to use the let keyword wherever possible for better memory management using immutability. However, when working with singletons and instance of classes, mutable variables can be really useful. For example, you may have a list of menuItems that gets updated at various points in your application. If you were passing around a single instance of the class, you may want the class property to allow updates accordingly:

class Menu
{
  var menuItems: [MenuItem] = []
}

This is directly opposite of the functional best practices, but there are clear and obvious times when this approach is better than a strictly functional practice of passing by value.

OOP Patterns in Swift

Factory Pattern

protocol Decimal
{
  func stringValue() -> String

  // factory pattern
  static func make(string : String) -> Decimal
}

typealias NumberFactory = (String) -> Decimal

// Number implementations with factory methods
struct NextStepNumber: Decimal
{
  private var nextStepNumber: NSNumber

  func stringValue() -> String
  {
    return nextStepNumber.stringValue
  }

  // factory pattern
  static func make(string: String) -> Decimal
  {
    return NextStepNumber(nextStepNumber: NSNumber(value: (string as NSString).longLongValue))
  }
}

struct SwiftNumber: Decimal
{
  private var swiftInt: Int

  func stringValue() -> String
  {
    return "\(swiftInt)"
  }

  // factory pattern
  static func make(string : String) -> Decimal
  {
    return SwiftNumber(swiftInt: (string as NSString).integerValue)
  }
}

// Usage
SwiftNumber.make(string: "2") // Returns a SwiftNumber instance

Singleton Pattern

//
// SINGLETON PATTERN in Swift
//
class Theme
{
  static let sharedInstance = Theme()

  private init()
  {
    // Private initialization to ensure just one instance is created.
  }
}

// Usage
let themeSingleton = Theme.sharedInstance