Search code examples
swiftinstanceconstantsvarlet

Whether to use var or let during instances creation in Swift?


What should be used to create the instances of classes in Swift and why?

please explain the usage of let and var during the instances creation in Swift

below is the code :-

class ConstantTest{
    let constant: String
    init(constant: String) {
        self.constant = constant
    }
    func printConstant() {
        print(constant)
    }
}

let constanttest = ConstantTest(constant: "Hello")
constanttest.printConstant()

var test = ConstantTest(constant: "Hie")
test.printConstant()

Solution

  • Use let if:

    • it is a constant (or in the case of reference types like class, if the reference cannot be replaced with another reference); and
    • you're able to set it during the initialization process.

    But if you need to be able to change it at a later point, use var, such as true variables whose values are not constant (or in the case of reference types, if you need to replace it with another instance). But variables and properties whose values are not set during the initialization process, you have to use var. For example, lazy stored properties use var because their value is not set when the initialization process completes, but only when you first reference it. Another example includes view controllers' references to their outlets that are hooked up only when the view hierarchy is created at a later point.

    Needless to say, computed properties use var, too.

    But, if you can use let, you should do so, as it's easier to write safe code if you know what is a constant and what is a variable. In your example, you'd use let.

    Note: In the case of reference types, like class types, let does not mean that that the object itself is necessarily immutable, merely that you cannot replace it with another instance. If you want to enjoy control over whether it's immutable or not, consider using a value type (e.g. a struct).


    Let me see if I can make that final note more clear. Consider:

    class Foo {
        var value: String
        init(value: String) {
            self.value = value
        }
    }
    

    Then the following is permitted:

    let obj = Foo(value: "a")
    obj.value = "b"           // changing mutable property of reference type, Foo, is permitted
    

    But the following is not:

    let obj = Foo(value: "a")
    obj = Foo(value: "b")     // replacing `obj` with a new instance of `Foo`, is not
    

    If you don't want to be able to change value property, you can define value to be immutable (or at least, not publicly mutable), e.g.:

    class Foo {
        let value: String      // or `private(set) var value: String`
        init(value: String) {
            self.value = value
        }
    }
    

    Or don't define Foo as class (a reference type) and instead define it to be a struct (a value type):

    struct Foo {
        var value: String
        init(value: String) {
            self.value = value
        }
    }
    
    let obj = Foo(value: "a")
    obj.value = "b"            // this is not permitted, because Foo value-type, `obj`, was declared with `let`, making it immutable
    

    Note, that final example, declaring Foo as a value type (a struct) does change it fairly fundamentally, e.g.

    var obj1 = Foo(value: "a")
    var obj2 = obj1            // this value is a copy of `obj1` not a reference to the same object that `obj1` pointed to
    obj1.value = "b"
    print("\(obj1.value)")     // will print "b"
    print("\(obj2.value)")     // will print "a"
    

    But value types, while it requires a slightly different mindset to use them, are incredibly useful for easily writing safe code. See WWDC 2015 Building Better Apps with Value Types in Swift.