¿Cuál es la diferencia entre "let" y "var" en Swift?
¿ Cuál es la diferencia entre let
y var
en 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
La let
palabra clave define una constante:
let theAnswer = 42
No se theAnswer
puede cambiar después. Es por eso que weak
no se puede escribir nada usando let
. Deben cambiar durante el tiempo de ejecución y usted debe usarlos var
en su lugar.
El var
define 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.
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 var
y let
son referencias , por lo tanto let
es una referencia constante . El uso de tipos fundamentales realmente no muestra en qué let
se 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"
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
constant
no se puede cambiar una vez establecido, mientras que avariable
se 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 classes
son mutable
un 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 struct
puede cambiar su estado de mutabilidad:
var
+ struct
= mutable
Se puede reasignar o cambiar
let
+ struct
= * immutable
o mejor dicho unmodifiable
[Acerca de] [Ejemplo] [Ejemplo] = constante de valor No se
puede reasignar ni cambiar
*inmutable - testStructMutability
prueba 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
- Indica que esta función cambia los valores de las propiedades internas.
- Solo puedes llamar a la función mutante en la
var
variable - 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
}
inout
dentro de una función
inout
le permite reasignar/modificar un valor pasado (original).- Sólo puedes pasar
var
la variable dentroinout
del parámetro - El resultado es visible cuando finaliza la función.
inout
tiene el siguiente flujo:
- El valor pasado se copia en el valor copiado antes de una función llamada.
- 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
let
siempre que puedas. Úselovar
cuando sea necesario.
[Estructura mutada]