Start learning free

LESSON 206 OF 415 · FUNCTIONS & CLASSES

Creating Objects in Swift

Lesson Read the full explanation

TL ; DR:

  • An object is an instance of a class — a real, usable copy made from the blueprint.


  • You create one by calling the class name like a function:

    let rex = Dog()
    

  • Each call creates a separate object, even if they all come from the same class.



Full lesson:

In the previous lesson you defined the Dog class — the blueprint. But a blueprint isn't a dog. To get an actual dog you can interact with, you need to create an instance of the class. An instance is also called an object.


Creating a new object

To create a new object in Swift, call the class name like a function — this invokes the class's initializer:

let rex = Dog()

What this line does:

  • Dog() calls the initializer and creates a fresh Dog instance.

  • let rex declares a constant named rex that holds a reference to that object.

  • The = connects the two — rex now refers to the freshly-created dog.


Many objects from one class

You can call Dog() as many times as you want, and each call gives you a brand-new, independent object:

let rex   = Dog()
let buddy = Dog()
let luna  = Dog()

rex, buddy, and luna are all Dog objects, but they're different objects. Changing one won't affect the others — they share the blueprint but live their own lives.


Your task

The Dog class is already defined for you. Inside mainFunction, create three separate Dog objects named rex, buddy, and luna. The starter code checks each variable with != nil, so declare each one with the optional type Dog?, for example let rex: Dog? = Dog(). The pre-filled checks then print:

rex exists
buddy exists
luna exists
STEP 1 OF 3
    Ctrl + Enter to check

    SWIFT · FUNCTIONS & CLASSES

    Creating Objects in Swift, explained

    Classes and objects

    A class describes what something looks like; an object (also called an instance) is one real thing built from that description. Defining Dog doesn't give you any dogs yet. To get one, you call the class name like a function, which runs the class's initializer:

    let rex = Dog()
    

    Here Dog() creates a fresh Dog and let rex declares a constant that holds a reference to it. Because Dog is a class, that constant refers to one object in memory; the constant fixes which object, not what is inside it.

    Many objects from one class

    Every call creates a new, independent object:

    class Dog {
    }
    
    let rex = Dog()
    let buddy = Dog()
    let luna = Dog()
    print(rex === buddy)   // false
    let alias = rex
    print(alias === rex)   // true
    

    The first comparison prints false, because rex and buddy are two objects. The second prints true: alias = rex doesn't create a copy, it makes a second name for the same object. Classes are reference types, so assigning one to another constant shares the object. Once the classes get fields, a change made through rex is also visible through alias, but not through buddy.

    The exercise and the optional type

    The starter code ends with three checks of the form if rex != nil { print("rex exists") }. For a check against nil to make sense, the constant must be an optional, a type that can hold either a value or nil. Optional types are written with a question mark, so the lesson declares each dog as Dog?:

    class Dog {
    }
    
    class Solution {
        func mainFunction() {
            let rex: Dog? = Dog()
            let buddy: Dog? = Dog()
            let luna: Dog? = Dog()
    
            if rex != nil { print("rex exists") }
            if buddy != nil { print("buddy exists") }
            if luna != nil { print("luna exists") }
        }
    }
    

    Running mainFunction prints rex exists, buddy exists and luna exists, one per line. Each constant was given a real Dog, so none is nil.

    If you write let rex = Dog() without the Dog? annotation, the type is plain Dog, which can never be nil. The comparison still runs and still prints, but the compiler warns comparing non-optional value of type 'Dog' to 'nil' always returns true. That is why the lesson spells out the optional type.

    What the initializer does

    An initializer is the code that sets an object up when it is created. For an empty class, Swift supplies one for you, which is why Dog() works without any extra code. The lessons on fields and constructors show how an object gets its starting data; for now it is enough to know that the parentheses in Dog() are a call, and that the call returns a brand-new object every time.

    Because each constant holds a reference, the constants themselves are small. Three constants for three dogs means three separate objects, and none of them knows about the others.

    Common mistakes

    • Forgetting the parentheses. Dog alone is the type itself; Dog() creates an object.
    • Thinking let freezes the object. It only stops you from pointing the constant at a different object. Properties declared with var can still change.
    • Expecting a copy. Assigning one class constant to another shares the object. Use a new Dog() when you want a separate one.
    • Using a name before declaring it. The three constants must be declared before the if lines that use them.

    Key takeaways

    • Call the class name with parentheses, Dog(), to create an object.
    • Each call makes a new, independent object.
    • Classes are reference types: === tells whether two names point to the same object.
    • A value can be compared with nil in a meaningful way only if its type is optional, such as Dog?.
    Keep going with SwiftAbout 340 step-by-step lessons, from your first line of code to coding interviews. Free to start.
    Start learning free