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

When to use self vs super

struct Point {
    let x: Int
    let y: Int
}
class Enemy {
    var life: Int = 2
    let position: Point

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

    func decreaseHealth (factor: Int) {
        life -= factor
    }

}

class SuperEnemy: Enemy {
    var isSuper: Bool = true

    override init(x: Int, y: Int) {
        super.init(x: x, y: y)

        self.life = 50
    }
}

I don't understand why we use super.init(x: x, y: y) and than use self to change self.life value to 50. Why wouldn't it be super.life?

3 Answers

Hey Kevin Her,

Basically what's happening here is the superclass Enemy has two properties, life of type Int, and position of type Point. The life property has a default value of 2. The initializer of the enemy class accepts two Int values as arguments to create and assign a Point value to the position property.

Next, when we create a subclass of Enemy called SuperEnemy, this subclass will inherit all the properties, methods, and initializers of the super class. If you want to provide a new implementation of the initializer, you will need to override the initializer of the super class. Inside the body of the initializer, we use super to call the initializer of the super class. By calling through to the super class initializer, we can populate the properties we inherited with values. We can now change the default value of the inherited life property to 50. The reason why you use self to refer to this property is because you are referring to the property owned by this class itself.

In case I lost you:

SUPER:

1) You will use super to refer to the super classes implementation of an initializer/method

SELF:

1) Disambiguate between an initializer parameter and a property name

2) Reference a property/method from inside of a closure

3) Call through to another initializer in the same class

4) Reference a property/method of the class

Good Luck

Hello Kevin:

Steven Deutsch gave you a great explanation, and to add to his answer I would like to explain something about the self word.

Per apple's recommendation, you should use self when there is a potential confusion in names, and inside the body of a closure. In this example you are showing, you do not necessarily need to use self, since there are no naming confusions going on. You may ask: " confusions in name " ?

Here is an example of what I mean:

// Using the same struct from your example. 
// Lets say that instead of using the "member wise initializer" the struct provides.
// we want to create our own "initializer"

struct Point {
    let x: Int
    let y: Int

// Example 1
// Potential name confusion.

  init(x: Int, y: Int) {
     x = x
     y = y
}

// Example 2  
// No confusion

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

}

Notice how in example 1 there is no self. This may cause Xcode to be confused on what you really mean. Do you mean to use the parameter name or the property ? In example 2, we get rid of that confusion by the use of self, and telling Xcode that self.x is for the store property and not the parameter name.

So in your example, it could have been like this :

struct Point {
    let x: Int
    let y: Int
}

class Enemy {
    var life: Int = 2
    let position: Point

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

    func decreaseHealth (factor: Int) {
        life -= factor
    }

}

class SuperEnemy: Enemy {
    var isSuper: Bool = true

    override init(x: Int, y: Int) {
        super.init(x: x, y: y)

        life = 50
    }
}

I hope this helps you

Good luck

Thank you Steven and Jhoan for all the help. I definitely have a better understanding now. Much appreciation.