Welcome to the Treehouse Community

Want to collaborate on code errors? Have bugs you need feedback on? Looking for an extra set of eyes on your latest project? Get support with fellow developers, designers, and programmers of all backgrounds and skill levels here with the Treehouse Community! While you're at it, check out some resources Treehouse students have shared here.

Looking to learn something new?

Treehouse offers a seven day free trial for new students. Get access to thousands of hours of content and join thousands of Treehouse students and alumni in the community today.

Start your free trial

iOS

Brian Law
Brian Law
4,099 Points

Help with override in Swift

I'm confused about when to use override. I thought it was necessary when calling super.init, but an example in Apple's Swift guide indicates otherwise.

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

class RecipeIngredient: Food {
    var quantity: Int
    init(name: String, quantity: Int) {
        self.quantity = quantity
        super.init(name: name)
    }
    override convenience init(name: String) {
        self.init(name: name, quantity: 1)
    }
}

In this example, the RecipeIngredient init doesn't need override, but the convenience init does. I'm really lost here. Any help would be appreciated.

1 Answer

Thomas Dobson
Thomas Dobson
7,511 Points

Directly from Apple docs:

Overriding

A subclass can provide its own custom implementation of an instance method, type method, instance property, type property, or subscript that it would otherwise inherit from a superclass. This is known as overriding.

To override a characteristic that would otherwise be inherited, you prefix your overriding definition with the override keyword. Doing so clarifies that you intend to provide an override and have not provided a matching definition by mistake. Overriding by accident can cause unexpected behavior, and any overrides without the override keyword are diagnosed as an error when your code is compiled.

The override keyword also prompts the Swift compiler to check that your overriding class’s superclass (or one of its parents) has a declaration that matches the one you provided for the override. This check ensures that your overriding definition is correct.

Now lets look at the example you gave us. RecipeIngredient is a subclass of Food. It has a inherited property of name, and and the newly defined property (exclusive to RecipeIngredient) quantity. Both of these properties are being initialized for RecipeIngredients.

RecipeIngredient has inherited the convenience initializer. In order for it to leverage the quantity property, this initializer needs to be OVERRIDDEN. In the override the initializer has both name and quantity for the RecipeIngredient Class.

I hope this breakdown helps a bit.

class Food {
    var name: String
    init(name: String) {
        self.name = name
    }
    convenience init() {
        self.init(name: "[Unnamed]")
    }
}

class RecipeIngredient: Food {
    var quantity: Int
    init(name: String, quantity: Int) {
        self.quantity = quantity //initializes property quantity
        super.init(name: name) //initializes the inherited property name
    }
    override convenience init(name: String) { //overrides convenience to add quantity
        self.init(name: name, quantity: 1)
    }
}
Brian Law
Brian Law
4,099 Points

Thanks for the answer. I think I'm closer to getting this, but am still missing something. So because the RecipeIngredient convenience init has quantity, it needs to to override, right?

But what I don't understand is why the designated init for RecipeIngredient doesn't need an override. It's still using both name and quantity. In this example from Object Oriented Swift, he does need the override in the designated init. I'm just not getting what makes them different

class Tower {
    let position: Point
    var range: Int = 1
    var strength: Int = 1

    init(x: Int, y: Int){
        self.position = Point(x: x, y: y)
    }

    func fire(at enemy: Enemy){
        if isInRange(of: enemy){
            enemy.decreaseLife(by: strength)
            print("enemy hit")
        } else{
            print("enemy out of range")
        }
    }

    func isInRange(of enemy: Enemy) -> Bool {
        let availablePositions = position.surroundingPoints(inRange: range)
        for point in availablePositions{
            if (enemy.position.x == point.x) && (enemy.position.y == point.y){
                return true
            }
        }

        return false
    }
}

class LaserTower: Tower {

    override init(x: Int, y: Int) {
        super.init(x: x, y: y)
        self.range = 100
        self.strength = 100
    }

    override func fire(at enemy: Enemy) {
        while enemy.life >= 0 {
            enemy.decreaseLife(by: strength)
        }

        print("Enemy desomated")
    }
}

Edit I figured out how to distinguish between the cases. For reference if anyone else has this question, "Initializing Superclasses" in intermediate Swift helped clear it up.