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

Pushkar Kadam
Pushkar Kadam
3,823 Points

What exactly is happening when we use self in init?

I have difficulty in understanding what init is exactly used for. In the track they used the following code.

let x1 = 0
let y1 = 0

let coordinate1: (x: Int, y: Int) = (0,0)
coordinate1.x

struct Point {
    let x: Int
    let y: Int

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


    /// Returns the surrounding points in range of
    /// the current one
    func points(inRange range: Int = 1) -> [Point]{
        var results = [Point]()

        let lowerBoundOfXRange = x - range
        let upperBoundOfXRange = x + range

        let lowerBoundOfYRange = y - range
        let upperBoundOfYRange = y + range

        for xCoordinate in lowerBoundOfXRange...upperBoundOfXRange {
            for yCoordinate in lowerBoundOfYRange...upperBoundOfYRange {
                let coordinatePoint = Point(x: xCoordinate, y: yCoordinate)
                results.append(coordinatePoint)
            }
        }
        return results
    }
}

I have come to think of it that struct Point creates a data type. Then, in that we are creating two variables. Then we use init which assigns theses two variables x and y to self.x and self.y respectively. I am not able to understand what it does.

Then, we assign the data type Point to the variable results. Does that mean that we are expecting two values in return i.e. x and y.

I am not sure what happens exactly. May someone please explain me how init works and when we return the results, I would like to know if we are returning an array or just a tuple.

1 Answer

Xavier D
PLUS
Xavier D
Courses Plus Student 5,840 Points

Hey PushKar,

When you are denote self, you are referring to the object of where you are writing your code. For instance, if I am writing code inside an object like below...

struct HeroCharacter
{
    let head: Int
    let arm1: Int
    let arm2: Int
    let leg1: Int
    let leg2: Int

    init(leg1: Int, leg2: Int)
    {
        self.leg1 = leg1
        self.leg2 = leg2
    }
}

... above, I used self to inform the compiler that I'm referring to the struct itself (i.e. the struct's instance, not the type itself). Every object that you create, if it has stored properties, they MUST have initial values before you can use the object. Struct have a memberwise initializer to give values to the stored properties (although you can just write your own init method like I did above for the two legs), but classes do not come with a memberwise initializer to give values to the stored properties.. thus for the following class....

class HeroCharacter
{
    let head: Int
    let arm1: Int
    let arm2: Int
    let leg1: Int
    let leg2: Int
}

...the complier will complain that the above class has no initializers. Again, ALL STORED PROPERTIES MUST HAVE VALUES. Therefore, I can fix the above but just putting in some values like so...

class HeroCharacter
{
    let head: Int = 1
    let arm1: Int = 2
    let arm2: Int = 3
    let leg1: Int = 4
    let leg2: Int = 5
}

however, we may not always know the values the stored properties are going to be. For example, say if we want t make a video game where we allow the user to customize the body of the hero (i.e., hear, arms and legs). Well, since we don't know what values the user wants to use, we can't set values just yet. But if we can't set the values that we don't know about, how to we get around the compiler since all stored properties need to have values? we get around the complier by using initializers....

class HeroCharacter
{
    let head: Int // My head has no value until the user sets it, the compiler will complain about this...
    let arm1: Int // My arm has no value until the user sets it, the compiler will complain about this...
    let arm2: Int // My arm has no value until the user sets it, the compiler will complain about this...
    let leg1: Int // My leg has no value until the user sets it, the compiler will complain about this...
    let leg2: Int // My leg has no value until the user sets it, the compiler will complain about this...

    init (head: Int, arm1: Int, arm2: Int, leg1: Int, leg2: Int ) // declaring init to give substituted values until the user sets them
    {
        self.head = head // Yay, now my head has a value so now the compiler won't complain. I still don't have a REAL head until the user sets it
        self.arm1 = arm1 // Yay, now.. "" "" "" .. "" "" ""
        self.arm2 = arm2
        self.leg1 = leg1 // self allows you to access properties and methods of an object using dot notation. self.leg1 refers to the stored property of clone while leg1 refers to a type that is labeled in the init's parameter list. The leg1 in init's parameter list gives value to Clone's stored properties called leg1, but it's denoted as self.leg1 to distinguish it from the leg1 in the init's parameter list.
        self.leg2 = leg2
    }
}

See. Now with init, all stored properties have values, therefore, the object is ready for use...

class HeroCharacter
{
    let head: Int, arm1: Int, arm2: Int, leg1: Int, leg2: Int

    init (u: Int, v: Int, x: Int, y: Int, z: Int )
    {
        self.head = u // Although it's convention to label the types in the init's parameter list the same name as the stored properties, you can get away with naming them anything you want...as long as you use them to assign values to all properties, the complier won't complain...
        self.arm1 = v
        self.arm2 = x
        self.leg1 = y
        self.leg2 = z
    }
}

Also without the stored properties having an initializers, Xcode will not be able to generate a parameter list for when you decide to create an instance. Also remember whatever labels to denote in the designated init method, will show up when you create an instance....

class HeroCharacter
{
    let head: Int, arm1: Int, arm2: Int, leg1: Int, leg2: Int

    init (u: Int, v: Int, x: Int, y: Int, z: Int )
    {
        self.head = u
        self.arm1 = v
        self.arm2 = x
        self.leg1 = y
        self.leg2 = z
    }
}

let superHero = HeroCharacter( // u,v,x,y & z labels will show up right here right after you type out the first parenthesis.