Swift Classes – Part 2

Inheritance

A class can inherit methods, properties, and other characteristics from another class. When one class inherits from another, the inheriting class is known as a subclass, and the class it inherits from is known as its superclass. Inheritance is a fundamental behavior that differentiates classes from other types in Swift.

A simple example of inheritance:

class AClass {
    func doSomething() {
        println("Hello from AClass")
    }
}

class Subclass: AClass  {
}

let base_object = AClass()
base_object.doSomething()
//> Hello from AClass


let enhanced_object = Subclass()
enhanced_object.doSomething()
// > Hello from AClass

Overriding

You can override methods in order to provide custom behaviour. To override a method write the override keyword before the method declaration:

class AClass {
    func doSomething() {
        println("Hello from AClass")
    }
}

class Subclass: AClass  {
    override func doSomething() {
        println("Hello from Subclass")
    }
}

let base_object = AClass()
base_object.doSomething()
//> Hello from AClass


let enhanced_object = Subclass()
enhanced_object.doSomething()
//> Hello from Subclass

You can use the super keyword to call any method from the superclass.

...

class Subclass: AClass  {
    override func doSomething() {
        super.doSomething()

        println("Hello from Subclass")
    }
}

let enhanced_object = Subclass()
enhanced_object.doSomething()
//> Hello from AClass
//> Hello from Subclass

Base class

A class that does not inherit from another class is called a base class, for example:

class User {
    var name: String!
    var age: Int!

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

The iOS and Mac OS classes ussualy inherit from NSObject, either directly on indirectly. If you have a mixt codebase I would encourage you to subclass NSObject when creating a new class:

Swift classes that are subclasses of NSObject:

  • are Objective-C classes themselves
  • use objc_msgSend() for calls to (most of) their methods
  • provide Objective-C runtime metadata for (most of) their method implementations

Swift classes that are not subclasses of NSObject:

  • are Objective-C classes, but implement only a handful of methods for NSObject compatibility
  • do not use objc_msgSend() for calls to their methods (by default)
  • do not provide Objective-C runtime metadata for their method implementations (by default)

Subclassing NSObject in Swift gets you Objective-C runtime flexibility but also Objective-C performance. Avoiding NSObject can improve performance if you don’t need Objective-C’s flexibility.

from stackoverflow Swift native base class or NSObject

Protocols

Protocols are declared in a similar way to classes.

protocol MyFirstProtocol {
    // I do nothing

Protocols describe methods, properties and other requirements that are needed for a specific task. For example theUITableViewDelegate protocol lists all the methods that can be used to react to user events and configure a table view.

Note: you can mark a method as optional using the @optional keyword. All of the methods from UITableViewDelegate are optional. When you do not use the @optional keyword that method is required. The swift compiler will throw an error if a class conforms to a protocol and does not implement the required methods.

A class can conform to a protocol by placing its name after the type’s name separated by a colon, as part of their definition. Multiple protocols can be listed, and are separated by commas:

class AnotherSwiftClass: MyFirstProtocol, AnotherProtocol {
    ...
}

If the class inherits from another one, make sure to put the superclass name before the protocol list.

class AnotherSwiftClass: AClass, MyFirstProtocol, AnotherProtocol {
    ...
}

Note: Protocols use the same syntax as normal methods, but are not allowed to specify default values for method parameters.

One of the most overused design pattern in iOS is delegation. A class can delegate a part of it’s responsibilities to an instance of another class. This design pattern is implemented by defining a protocol that encapsulates the delegated responsibilities, such that a conforming type (known as a delegate) is guaranteed to provide the functionality that has been delegated.

Here is an example, the Player class delegates the shooting logic to the weapon:

protocol Targetable {
    var life: Int { get set }
    func takeDamage(damage: Int)
}

protocol Shootable {
    func shoot(target: Targetable)
}

class Pistol: Shootable {
    func shoot(target: Targetable) {
        target.takeDamage(1)
    }
}

class Shotgun: Shootable {
    func shoot(target: Targetable) {
        target.takeDamage(5)
    }
}

class Enemy: Targetable {
    var life: Int = 10

    func takeDamage(damage: Int) {
        life -= damage
        println("enemy lost \(damage) hit points")

        if life <= 0 {
            println("enemy is dead now")
        }
    }
}

class Player {
    var weapon: Shootable!

    init(weapon: Shootable) {
        self.weapon = weapon
    }

    func shoot(target: Targetable) {
        weapon.shoot(target)
    }
}

var terminator = Player(weapon: Pistol())

var enemy = Enemy()

terminator.shoot(enemy)
//> enemy lost 1 hit points
terminator.shoot(enemy)
//> enemy lost 1 hit points
terminator.shoot(enemy)
//> enemy lost 1 hit points
terminator.shoot(enemy)
//> enemy lost 1 hit points
terminator.shoot(enemy)
//> enemy lost 1 hit points

// changing weapon because the pistol is inefficient
terminator.weapon = Shotgun()

terminator.shoot(enemy)
//> enemy lost 5 hit points
//> enemy is dead now

Challenges

  • create a Shape base class and derive from it CircleSquare and RectangleShape should have two methods area() -> Float and perimeter() -> Float that both return 0. Implement the methods and add the necessary properties on Circle,Square and Rectangle.
  • create the same classes from the first exercise, but this time make Shape a protocol
  • add a resistance property to the Targetable protocol and reduce the damage taken by the enemy. Obs: you will need to change the life property type to Float in order to do this.

In case you missed it, check out Part 1 of this tutorial. And this is a complete guide to Object Oriented Programming in Swift.

If you found this useful please take a moment to share this with your friends :)

1 Star2 Stars3 Stars4 Stars5 Stars (5 votes, average: 5.00 out of 5)
Loading...

  4 comments for “Swift Classes – Part 2

  1. minecraft
    June 30, 2014 at 4:47 pm

    Your style is so unique compared to other people I’ve read stuff from.
    Many thanks for posting when you have the opportunity, Guess
    I’ll just bookmark this web site.

  2. virant porwal
    April 17, 2015 at 11:58 am

    Really Nice…..uniq and understandable.

  3. GHz
    June 10, 2015 at 2:51 am

    Huge thanks!

    This is an excellent resource.

Leave a Reply

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

This site uses Akismet to reduce spam. Learn how your comment data is processed.

Subscribe
We send about one email per week with our latest tutorials and updates
Never display this again :)