¿Cuál es la diferencia entre "let" y "var" en Swift?

Resuelto Edward asked hace 10 años • 32 respuestas

¿ Cuál es la diferencia entre lety varen el lenguaje Swift de Apple?

Según tengo entendido, es un lenguaje compilado pero no verifica el tipo en el momento de la compilación. Me confunde. ¿Cómo sabe el compilador sobre el error de tipo? Si el compilador no verifica el tipo, ¿no es un problema con el entorno de producción?

Este error aparece cuando intento asignar un valor a let:

No se puede asignar a la propiedad: 'nombrevariable' es una constante 'let'
Cambie 'let' a 'var' para hacerlo mutable

Edward avatar Jun 03 '14 02:06 Edward
Aceptado

La letpalabra clave define una constante:

let theAnswer = 42

No se theAnswerpuede cambiar después. Es por eso que weakno se puede escribir nada usando let. Deben cambiar durante el tiempo de ejecución y usted debe usarlos varen su lugar.

El vardefine una variable ordinaria.

Qué es interesante:

No es necesario conocer el valor de una constante en el momento de la compilación , pero debes asignar el valor exactamente una vez.

Otra característica extraña:

Puede utilizar casi cualquier carácter que desee para nombres de constantes y variables, incluidos los caracteres Unicode:

let 🐶🐮 = "dogcow"

Extractos de: Apple Inc. "El lenguaje de programación Swift". iBooks. https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewBook?id=881256329


Wiki de la comunidad

Debido a que los comentarios solicitan agregar otros datos a la respuesta, conviértalo en una respuesta wiki comunitaria . No dudes en editar la respuesta para mejorarla.

clt60 avatar Jun 02 '2014 19:06 clt60

Según el libro del lenguaje de programación Swift

Al igual que C, Swift usa variables para almacenar y hacer referencia a valores mediante un nombre identificativo. Swift también hace un uso extensivo de variables cuyos valores no se pueden cambiar. Se conocen como constantes y son mucho más poderosas que las constantes en C.

Ambos vary letson referencias , por lo tanto letes una referencia constante . El uso de tipos fundamentales realmente no muestra en qué letse diferencian de const. La diferencia viene al usarlo con instancias de clase (tipos de referencia):

class CTest
{
    var str : String = ""
}

let letTest = CTest()
letTest.str = "test" // OK

letTest.str = "another test" // Still OK

//letTest = CTest() // Error

var varTest1 = CTest()
var varTest2 = CTest()
var varTest3 = CTest()

varTest1.str = "var 1"
varTest2.str = "var 2"
varTest3 = varTest1
varTest1.str = "var 3"

varTest3.str // "var 3"
Krzak avatar Jun 24 '2014 16:06 Krzak

rápido dejar vs var

let- constant
var-variable

[Constante vs variable]
[Estructura vs Clase]

El documento oficial docs.swift.org dice

El valor de a constantno se puede cambiar una vez establecido, mientras que a variablese puede establecer con un valor diferente en el futuro.

Esta terminología en realidad describe un mecanismo de reasignación .

Mutabilidad

Mutabilidad - modificable - el estado del objeto se puede cambiar después de la creación [Acerca de]

Valor y tipo de referencia [Acerca de]

Tipo de referencia (clase)

Los Swift classesson mutableun priorato

var+ class
Se puede reasignar o cambiar

let+ class= constante de dirección No se
puede reasignar y se puede cambiar

Valor (estructura, enumeración)

Swift structpuede cambiar su estado de mutabilidad:

var+ struct= mutable
Se puede reasignar o cambiar

let+ struct= * immutableo mejor dicho unmodifiable[Acerca de] [Ejemplo] [Ejemplo] = constante de valor No se
puede reasignar ni cambiar

*inmutable - testStructMutabilityprueba de verificación

Experimentos:

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"
    }
}

Posibles casos de uso

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- Funciones de la estructura mutante

Puedes marcar el método de una estructura comomutating

  1. Indica que esta función cambia los valores de las propiedades internas.
  2. Solo puedes llamar a la función mutante en la varvariable
  3. El resultado es visible cuando finaliza la función de mutación.
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
}

inoutdentro de una función

  1. inoutle permite reasignar/modificar un valor pasado (original).
  2. Sólo puedes pasar varla variable dentro inoutdel parámetro
  3. El resultado es visible cuando finaliza la función.

inouttiene el siguiente flujo:

  1. El valor pasado se copia en el valor copiado antes de una función llamada.
  2. El valor copiado se asigna al valor pasado una vez finalizada la función.
//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
}     

*Los que robas son capaces de mutar.let + struct

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

Úsalo letsiempre que puedas. Úselo varcuando sea necesario.

[Estructura mutada]

yoAlex5 avatar Dec 06 '2019 19:12 yoAlex5