Mobile Development

Object Oriented Programming

A tenant of good source code is something that is reusable and easy to read. If you can create something once and reuse it, you can:

  1. Write less code
  2. Have an easier time maintaining your code base
  3. Reuse your code in other projects

Writing code using the principles of OOP will allow you to accomplish the above tasks while maintaining logical separation of roles between your objects.

Object oriented programming (OOP) is a programming paradigm based on the concept of "objects", which are data structures that contain data, in the form of fields, often known as attributes; and code, in the form of procedures, often known as methods. [1]

Definitions

Let's frame out a few terms that we will use to describe Object Oriented Programming and associated concepts.

  • Base Class - Parent class. For example, we are all human. Human would be our base class.
  • Class - A definition of a set of properties and functions that are related.
  • Inheritance - When a class inherits from a base class, it also inherits all of its public properties and functions. A human typically consists of a set of organs plus functions such as sleep and wake.
  • Instance - A single occurance of a class.
  • Object - A class that has been created and initialized.
  • Object Oriented - A programming concept where collections of objects are used to define an application.
  • OOP - An acronoym referring to Object Oriented Programming
  • Protocol - A set of functions and properties that a class will need to implement. Differs from inheritance in that the implementation has not yet been defined. Now that we have a vocabulary, let's move into some detail.
  • Superclass - Another term for Base Class.

Details

Let's talk about the ways Swift can help you rock out OOP.

Defining a class

And organize your code into reusable objects with a class:

class ExampleClass {

    var memberVariable:String

    init() {
        self.memberVariable = "Initial value."
    }

    func exampleFunction(thisIsFun:Bool) -> String {

        var returnValue = "No, this isn't fun."
        if thisIsFun {
            returnValue = "Yes, this is fun!"
        }

        return returnValue
    }
}

var exampleClass = ExampleClass()
print("We created a class and its member variable contains \(exampleClass.memberVariable) )"

Inheritance

A class can inherit another class and therefore capture its methods as its own. A subclass inherits the superclass.

import UIKit

class YourViewController: UIViewController {

}

In this simple example above, we are using Swift to describe YourViewController which inherits all the methods of UIViewController. When we inherit the superclass, we can not only obtain functionality but can override that functionality as we want.

import UIKit

class YourViewController: UIViewController {
    override func viewWillAppear(animated: Bool) {
        super.viewWillAppear(animated)
        view.backgroundColor = UIColor.blackColor()
    }
}

It is important to note that when calling functions from the superclass, it is often the case you will be wanting to call super of the same method. This allows for the super's function to also be called. In the above example, we are calling super.viewWillAppear(animated) to allow for the UIViewController's method (viewWillAppear) to also be called and perform any necessary initialization.

Protocols

Protocols are similar to inheritance in that we obtain a set of functions and properties through declaration. They differ in that you are required to define these methods when implementing the protocol.

import Foundation

// Defines a protocol
protocol ExampleProtocol {

    var maxValue:Int {get set}

    func generateRandomNumber() -> Int
}

// Defines the class which implements the protocol
class ExampleImplementation: ExampleProtocol {

    var maxValue:Int

    init (initialMaximumValue:Int) {
        maxValue = initialMaximumValue
    }

    func generateRandomNumber() -> Int {
        return random() % maxValue;
    }
}

// Example usage
let example = ExampleImplementation(initialMaximumValue: 10)
example.generateRandomNumber()

A real-world example, extending our previous, would be to conform YourViewController to the UITableViewDataSource protocol:

import UIKit

class YourViewController: UIViewController, UITableViewDataSource {

    ///////////
    // Inheritance
    override func viewWillAppear(animated: Bool) {
        view.backgroundColor = UIColor.blackColor()
    }

    ///////////
    // Protocol
    // Required: filling out protocol functions

    // protocol definition 1
    func numberOfSectionsInTableView(tableView: UITableView) -> Int {
        return 1
    }

    // protocol definition 2
    func tableView(tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return 1
    }

    // protocol definition 3
    func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell {

        var tableCell = UITableViewCell()
        return tableCell
    }
}

Polymorphism

Polymorphism allows you to write more generic code that works with families of objects, rather than writing code for a specific class. [2]

var x = UILabel()
var y = UITextView()
var z = UIButton()

func updateTheTag(control:UIView, updatedTag:Int) {
    control.tag = updatedTag
}

updateTheTag(x, 1)
updateTheTag(y, 2)
updateTheTag(z, 3)

In this above example, UILabel, UITextView and UIButton all derive from the base class of UIView and that base class defines a tag property. Although each of these classes may have a specific purpose, they all can access their base classes properties in a generic way.

Swift types

Enumerations

An enumeration defines a common type for a group of related values and enables you to work with those values in a type-safe way within your code. [3]

enum CompassPoint {
    case North
    case South
    case East
    case West
}

// Int type
enum AgesOfChildren:Int {
    case John = 20
    case Jacob = 25
    case Jingleheimer = 30
    case Schmidt = 35
}

// String type
enum SectionHeader : String {
    case FirstColumn = "Column 1"
    case SecondColumn = "Column 2"
    case ThirdColumn = "Column 3"
    case FourthColumn = "Column 4"
    case FifthColumn = "Column 5"
}

Structures vs Classes

Apples documentation goes into detail defining structures and classes. That resource is listed as number 5 below, and is summarized here.

Classes and structures are general-purpose, flexible constructs that become the building blocks of your program’s code.

Similarities:

  • Define properties to store values
  • Define methods to provide functionality
  • Define subscripts to provide access to their values using subscript syntax
  • Define initializers to set up their initial state
  • Be extended to expand their functionality beyond a default implementation
  • Conform to protocols to provide standard functionality of a certain kind

Structures

struct Beer {
    var name:String
    var ounces:Float
    var alcoholContent:Float
    var bitterness:Int
}

var stoneIPA = Beer(name:"Stone IPA", ounces:22.0, alcoholContent:6.9, bitterness:85)

[Video] Value versus References

When talking about classes there is one key difference and that is value versus reference. Structures are passed by value where classes are passed by reference.

Swift Tutorial: Intermediate 02 - Value and Refence Types

Classes

Now classes are similar to structures with a few exceptions, including being passed as reference types. Classes also allow for inheritance, which enables us to define more complex object schemes, such as the following:


class Human {
    var name:String
    var type:String
    var age:Int
    var spouse:Human?

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

    func becomeMarried(spouse:Human) -> () {
        self.spouse = spouse
    }
}

let me = Human(name: "Jeff", type: "Human", age: 34)
me.spouse

let wife = Human(name: "Katie", type: "Human", age: 32)
me.becomeMarried(wife)
wife.spouse

class Baby : Human {
    var diaperChangesToday:Int

    override init(name: String, type: String, age: Int) {
        diaperChangesToday = 0
        super.init(name: name, type: type, age: age)
    }

    func incrementDiaperChanges() -> String {
        diaperChangesToday++
        return("\(diaperChangesToday) diapers? C'mon now!")
    }
}

let newBaby = Baby(name: "Raleigh", type: "Human", age: 0)
newBaby.incrementDiaperChanges()
newBaby.incrementDiaperChanges()
newBaby.incrementDiaperChanges()

References

An Introduction to Object-Oriented Programming - http://blog.codeclimate.com/blog/2014/06/19/oo-swift/

[1] Object-oriented Programming http://en.wikipedia.org/wiki/Object-oriented_programming

[2] Swift Programming 101: Inheritance & Polymorphism http://www.iphonelife.com/blog/31369/swift-programming-101-inheritance-polymorphism

[3] Enumrations https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Enumerations.html

[4] Protocols https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html#//apple_ref/doc/uid/TP40014097-CH25-XID_402

[5] Structures and Classes https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/ClassesAndStructures.html

[6] Protocols https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Protocols.html