• 20 hours
  • Medium

Free online content available in this course.

course.header.alt.is_video

course.header.alt.is_certifying

Got it!

Last updated on 7/4/19

Perform object initialization

Log in or subscribe for free to enjoy all this course has to offer!

Our classes now have properties, they allow us to store information. At this moment they will all have default values. This may be ok for some cases, but for others it would make little sense.

For example, that would be similar to having a default value of "New York City" for our destination object, when we want to visit lots of different places. It's cool for "New York City" to appear on our travel list once but not as the default option for all the trips. In fact, we can’t really predict what default option would be suitable in this case!

Uninitialized properties

For properties where it doesn't make sense to have any default value (because it would depend on a particular context of the object) it’s best to remove that default value altogether and give this responsibility to the code when an object is being created.

This applies to all the properties of our classes. Let's refactor the Entertainment class and remove the default values:

class Entertainment {
    var name: String
    var cost: Double
}

As you can observe, this results into an error stating that our class doesn't have an initializer.

What does that mean?

Initializer is a method that is called when an instance of a class is created. It's responsible for making sure ALL properties are ready to be used.

There are two ways resolve this issue:

  • Make properties without a default value Optional 

    class Entertainment {
        var name: String?
        var cost: Double?
    }
  • Assign values to them when an instance is created - within initializers

Declaring initializers

An initializer is a method. And a method is a function. Therefore, to declare an initializer we need to declare a function within the class's body: curly brackets. Only a couple of things are different:

  • it must use a dedicated name -  init 

  • and we don't need to use the  func   keyword.

If we don’t need to provide any values to any properties of an object, the initializing method can be just one without any parameters (which is a default one for any class).

init() {
    // initialization logic
}

To overcome errors in the Entertainment class without using optionals we could write the initialization logic within this initializer:

init() {
    name = "Broadway show"
    cost = 150
}

From a programming standpoint this approach is correct. Logically, however, it makes little sense as we are still insisting on providing default values at the object's creation. We simply defined those values in a different place - a new initializer. And the code that will create that object will have no control over the initial values of a new instance.

The solution is using parameters:

init(name: String, cost: Double) {
    // initialization logic
}

When we specify initializing parameters, our impulse is to describe them using labels that match the corresponding properties in our class. In our example:

  • A parameter called "name" provides a value to the name property

  • A parameter called "cost" provides a value to the cost property

Then inside the initializer we need to assign values supplied as parameters to the properties:

init(name: String, cost: Double) {
    name = name
    cost = cost
}

Well, this isn't going to work because it's easy to confuse what we are assigning to what. It's impossible to tell which cost  is a parameter and which is a property

Introducing "self"

To explicitly indicate a reference to a property, we must use a special keyword  self . It indicates that we’re addressing the object ITSELF. Then to access a property we use dot notation:

init(name: String, cost: Double) {
    self.name = name
    self.cost = cost
}

Now it's clear that we are assigning a parameter value to a corresponding property.

Using the keyword self is not always required. If there's no ambiguity, it's assumed to refer to a property. For example, if we came up with different labels for our parameters:

init(activityName: String, activityCost: Double) {
    name = activityName
    cost = activityCost
}

This code works fine.

What about NeXTDestination?

We've got some work to do to refactor our classes. Let's remove all the default values for our properties from their declarations and use initializers instead. Analyze the purpose of each property and decide whether it makes sense to have them as parameters or they can be assigned default values.

For those that will have a default value, assign it within initializer as well.

As usual, try to do it on your own!

Done? That was fast!
Done? That was fast!

Well done, let's review the results:

class Entertainment {
    //properties
    var name: String
    var cost: Double
    
    //initializer
    init(name: String, cost: Double) {
        self.name = name
        self.cost = cost
    }
}

class Destination {
    //properties
    var name: String
    var cost: Double
    var entertainmentOptions: [Entertainment]
    var accomplishments: [Entertainment]
    
    //initializer
    init(name: String, cost: Double, entertainmentOptions: [Entertainment]) {
        self.name = name
        self.cost = cost
        self.entertainmentOptions = entertainmentOptions
        accomplishments = []
    }
}

class Adventure {
    //properties
    var amountSpent: Double
    var destinations: [Destination]
    var placesVisited: [Destination]
    
    //initializer
    init(destinations: [Destination]) {
        self.destinations = destinations
        amountSpent = 0.0
        placesVisited = []
    }
}

Most of the properties will need to be set in the context of instance creation, therefore we have them as parameters in our initializers. Only a few can be safely assigned default values. Those are:

  • Entertainment:

    • N/a (all properties are suitable for parameters)

  • Destination:

    • accomplishments (at the beginning of an adventure, we will always start with no accomplishments, so we can use an empty array as a default value)

  • Adventure:

    • amountSpent (it's safe to assume we will start with zero spendings)

    • placesVisited (we will populate this variable along our journey, however always starting with an empty array)

Pretty good! You now know how to take advantage of initializers - Congrats!

Let's Recap!

  • There are two ways to use properties without a default value:

    • declaring them as optional

    • assign values to them in an initializer

  • An initializer is a function that is called when an instance is created. To create an initializer, we use the keyword init. Like any function, an initializer can have parameters.

  • The keyword  self   refers to the instance of a class in which it is called (the instance itself).

Example of certificate of achievement
Example of certificate of achievement