What is the difference between `let` and `var` in swift?

后端 未结 30 990
隐瞒了意图╮
隐瞒了意图╮ 2020-11-22 11:09

What is the difference between let and var in Apple\'s Swift language?

In my understanding, it is a compiled language but it does not check

相关标签:
30条回答
  • 2020-11-22 11:59

    let is used to define constants and var to define variables.

    0 讨论(0)
  • 2020-11-22 11:59

    let - constant
    var - variable

    [Constant vs variable]
    [Struct vs Class]

    Official doc docs.swift.org says

    The value of a constant can’t be changed once it’s set, whereas a variable can be set to a different value in the future.

    This terminology actually describes a reassign mechanism

    Mutability

    Mutability - changeable - object's state can be changed after creation[About]

    Value and Reference Type[About]

    Reference Type(Class)

    Swift's classes are mutable a-priory

    var + class
    It can be reassigned or changed

    let + class = constant of address
    It can not be reassigned and can be changed

    Value(Struct, Enum)

    Swift's struct can change their mutability status:

    var + struct = mutable
    It can be reassigned or changed

    let + struct = *immutable = constant of value
    It can not be reassigned or changed

    *immutable - check testStructMutability test

    Experiments:

    class MyClass {
        var varClass: NSMutableString
        var varStruct: String
        
        let letClass: NSMutableString
        let letStruct: String
        
        init(_ c: NSMutableString, _ s: String) {
            varClass = c
            varStruct = s
            
            letClass = c
            letStruct = s
        }
    }
    
    struct MyStruct {
        var varClass: NSMutableString
        var varStruct: String
        
        let letClass: NSMutableString
        let letStruct: String
        
        init(_ c: NSMutableString, _ s: String) {
            varClass = c
            varStruct = s
            
            letClass = c
            letStruct = s
        }
        
        
        //mutating function block
        func function() {
    //            varClass = "SECONDARY propertyClass" //Cannot assign to property: 'self' is immutable
    //            varStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'self' is immutable
        }
    
        mutating func mutatingFunction() {
            varClass = "SECONDARY propertyClass"
            varStruct = "SECONDARY propertyStruct"
        }
    }
    

    Possible use cases

    func functionVarLetClassStruct() {
        
        var varMyClass = MyClass("propertyClass", "propertyStruct")
        
        varMyClass.varClass = "SECONDARY propertyClass"
        varMyClass.varStruct = "SECONDARY propertyStruct"
        
    //        varMyClass.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
    //        varMyClass.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
        
        let letMyClass = MyClass("propertyClass", "propertyStruct")
        
        letMyClass.varClass = "SECONDARY propertyClass"
        letMyClass.varStruct = "SECONDARY propertyStruct"
        
    //        letMyClass.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
    //        letMyClass.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
        
        var varMyStruct = MyStruct("propertyClass", "propertyStruct")
        
        varMyStruct.varClass = "SECONDARY propertyClass"
        varMyStruct.varStruct = "SECONDARY propertyStruct"
        
    //        varMyStruct.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
    //        varMyStruct.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
        
        let letMyStruct = MyStruct("propertyClass", "propertyStruct")
        
    //        letMyStruct.varClass = "SECONDARY propertyClass" //Cannot assign to property: 'letMyStruct' is a 'let' constant
    //        letMyStruct.varStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letMyStruct' is a 'let' constant
        
    //        letMyStruct.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
    //        letMyStruct.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
        
    }
    

    mutating - Mutating Struct's Functions

    You can mark a struct's method as mutating

    1. Indicates that this function changes internal property values
    2. You are only able to call mutating function on var variable
    3. Result is visible when mutating function is finished
    func testStructMutatingFunc() {
        //given
        var varMyStruct = MyStruct("propertyClass", "propertyStruct")
        
        //when
        varMyStruct.mutatingFunction()
        
        //than
        XCTAssert(varMyStruct.varClass == "SECONDARY propertyClass" && varMyStruct.varStruct == "SECONDARY propertyStruct")
        
        // It is not possible to call a mutating function on a let variable
        let letMyStruct = MyStruct("propertyClass", "propertyStruct")
    //        letMyStruct.mutatingFunction() //Cannot use mutating member on immutable value: 'letMyStruct' is a 'let' constant
    }
    

    inout inside a function

    1. inout allows you to reassign/modify a passed(original) value.
    2. You are only able to pass var variable inside inout parameter
    3. Result is visible when function is finished

    inout has a next flow:

    1. passed value is copied into copied value before a function called
    2. copied value is assign into passed value after the function finished
    //InOut
    func functionWithInOutParameter(a: inout MyClass, s: inout MyStruct) {
        
        a = MyClass("SECONDARY propertyClass", "SECONDARY propertyStruct") //<-- assign
        s = MyStruct("SECONDARY propertyClass", "SECONDARY propertyStruct") //<-- assign
    }
    
    
    func testInOutParameter() {
    
        //given
        var varMyClass = MyClass("PRIMARY propertyClass", "PRIMARY propertyStruct")
        var varMyStruct = MyStruct("PRIMARY propertyClass", "PRIMARY propertyStruct")
    
        //when
        functionWithInOutParameter(a: &varMyClass, s: &varMyStruct)
    
        //then
        XCTAssert(varMyClass.varClass == "SECONDARY propertyClass" && varMyClass.varStruct == "SECONDARY propertyStruct")
        XCTAssert(varMyStruct.varClass == "SECONDARY propertyClass" && varMyStruct.varStruct == "SECONDARY propertyStruct")
        
        
        // It is not possible to pass let into inout parameter
        let letMyClass = MyClass("PRIMARY propertyClass", "PRIMARY propertyStruct")
        let letMyStruct = MyStruct("PRIMARY propertyClass", "PRIMARY propertyStruct")
    //        functionWithInOutParameter(a: &letMyClass, s: &letMyStruct) //Cannot pass immutable value as inout argument: 'letMyClass', 'letMyStruct' are 'let' constants
    }     
    

    *You steal are able to mutate let + struct

    func testStructMutability()  {
        //given
        let str: NSMutableString = "propertyClass"
        let letMyStruct = MyStruct(str, "propertyStruct")
        
        //when
        str.append(" SECONDARY")
        
        //then
        XCTAssert(letMyStruct.letClass == "propertyClass SECONDARY")
    }
    

    Use let whenever you can. Use var when you must.

    [Mutate structure]

    0 讨论(0)
  • 2020-11-22 12:00

    Very simple:

    • let is constant.
    • var is dynamic.

    Bit of description:

    let creates a constant. (sort of like an NSString). You can't change its value once you have set it. You can still add it to other things and create new variables though.

    var creates a variable. (sort of like NSMutableString) so you can change the value of it. But this has been answered several times.

    0 讨论(0)
  • 2020-11-22 12:02

    The

    Declaring Constants and Variables section of The Swift Programming Language documentation specifies the following:

    You declare constants with the let keyword and variables with the var keyword.

    Make sure to understand how this works for Reference types. Unlike Value Types, the object's underlying properties can change despite an instance of a reference type being declared as a constant. See the Classes are Reference Types section of the documentation, and look at the example where they change the frameRate property.

    0 讨论(0)
  • 2020-11-22 12:02

    The main difference is that var variable value can change, and let can't. If you want to have a user input data, you would use var so the value can be changed and use let datatype variable so the value can not be changed.

    var str      = "dog"  // str value is "dog"
    str          = "cat"  // str value is now "cat"
    
    let strAnimal = "dog" // strAnimal value is "dog"
    strAnimal     = "cat" // Error !
    
    0 讨论(0)
  • 2020-11-22 12:03

    Though currently I am still reading the manual, but I think this is very close to C/C++ const pointer. In other words, something like difference between char const* and char*. Compiler also refuses to update content, not only reference reassignment (pointer).

    For example, let's say you have this struct. Take care that this is a struct, not a class. AFAIK, classes don't have a concept of immutable state.

    import Foundation
    
    
    struct
    AAA
    {
        var inner_value1    =   111
    
        mutating func
        mutatingMethod1()
        {
            inner_value1    =   222
        }
    }
    
    
    let aaa1    =   AAA()
    aaa1.mutatingMethod1()      // compile error
    aaa1.inner_value1 = 444     // compile error
    
    var aaa2    =   AAA()
    aaa2.mutatingMethod1()      // OK
    aaa2.inner_value1 = 444     // OK
    

    Because the structs are immutable by default, you need to mark a mutator method with mutating. And because the name aaa1 is constant, you can't call any mutator method on it. This is exactly what we expected on C/C++ pointers.

    I believe this is a mechanism to support a kind of const-correctness stuff.

    0 讨论(0)
提交回复
热议问题