¿Cuál es la diferencia entre `let` y` var` en swift?


321

¿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 tiempo de 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?


35
let es para constantes, var es para variables.
Collin Henderson

2
@Edward ¿Qué quieres decir con verificación de ningún tipo en tiempo de compilación? Por lo que puedo decir, está estáticamente tipado, pero los tipos se infieren si el compilador puede resolverlo por sí mismo. Pero solo estoy en la página 25 ... ;-)
Joachim Isaksson

44
Esto es sobre el tema, pero es una pregunta mal formulada. Hay al menos 2 preguntas (i) diff entre let y var ; (ii) escriba safe vs type infer. Además, cuando el cartel mencionaba la etapa de producción , realmente se refería al tiempo de ejecución.
Kevin Le - Khnle

1
Además, var utilizado en variables que definen colecciones (matrices y diccionario) crea una colección mutable (no solo la referencia sino que el contenido de la colección puede modificarse. El otro uso de var es poder modificar los parámetros pasados ​​en una función: func foo (var bar: Int) le permitirá modificar la barra de parámetros localmente en el alcance de la función.
Laurent

Respuestas:


407

La letpalabra clave define una constante:

let theAnswer = 42

No theAnswerse puede cambiar después. Es por eso weakque no se puede escribir nada usando let. Deben cambiar durante el tiempo de ejecución y debes usarlo en su varlugar.

El vardefine una variable ordinaria.

Qué es interesante:

No es necesario conocer el valor de una constante en tiempo de compilación , pero debe asignar el valor exactamente una vez.

Otra característica extraña:

Puede usar casi cualquier carácter que desee para nombres 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

EDITAR

Debido a que los comentarios piden agregar otros hechos a la respuesta, convertir esto a la respuesta wiki de la comunidad . Siéntase libre de editar la respuesta para mejorarla.


1
C y C ++ también permiten identificadores Unicode, a través de UCN. Si el compilador admite cualquier codificación de fuente Unicode, puede usar los caracteres Unicode directamente. Por ejemplo auto 🐶🐮 = "dogcow";funciona en C ++ para clang.
bames53

131
@ bames53 está bien, solo no estoy seguro de querer depurar un programa como: if 😍 === 💝 { 💔 = ♠︎ }:);)
jm666

¿Se aplica a REPL? Porque puedes reasignar la constante en REPL.
Ahmed Al Hafoudh

1
Primero, como se señaló anteriormente, esto es totalmente diferente en el REPL. Segundo, si es una constante, no es mucho. Esto funciona bien en el compilador: let foo = [1,2,3]; foo [2] = 5; println ("(foo)") // [1, 2, 5]
Kevin Frost

31
A esta respuesta, aunque la más votada, le falta alguna mención de cómo se comporta let / var cuando se refiere a objetos en lugar de tipos de valores. La clave es que en ambos casos aún puede cambiar las propiedades del objeto, pero no puede modificar el puntero para referirse a otro objeto. Esto no es inmediatamente obvio a partir de ejemplos básicos que involucran enteros y cadenas.
SaltyNuts

33

De acuerdo con el libro del lenguaje de programación Swift

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

Ambos vary letson referencias , por letlo tanto, es una referencia constante . El uso de tipos fundamentales no muestra realmente qué tan letdiferente es const. La diferencia viene cuando se usa 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"

1
Esta terminología es totalmente errónea ... Todas las referencias son referencias constantes. No existe el concepto de "const ref". Una vez enlazada, una referencia siempre está limitada a la misma dirección de memoria y no se puede cambiar ni "quitar". Creo que quiere decir que var es un "puntero" y let es un "puntero constante"
AyBayBay

@AyBayBay Si bien lo que está escribiendo es correcto, por ejemplo, en C ++, creo que el fragmento anterior prueba, que no es el caso en Swift. Los punteros permitirían la aritmética del puntero y el acceso directo a la memoria, lo cual tampoco es el caso aquí. - Editar: no he encontrado evidencia de que todas las referencias sean de hecho constantes para todos los lenguajes de programación.
Krzak

Por cierto, según los punteros de Wikipedia son referencias
Krzak

2
Estoy de acuerdo en que su terminología es incorrecta. vary letno tiene nada que ver con si el identificador que está vinculado es una referencia o no. Si el tipo es un structtipo, conceptualmente es un valor. Si el tipo es a classes conceptualmente una referencia y la referencia es una constante si letse usa. Si CTestfuera una estructura, ninguna de sus letTesttareas funcionaría.
JeremyP

1
Si el tipo es un structtipo de valor, no tiene nada de conceptual. Lo mismo con class- tipo de referencia. Al modificar un tipo de valor, crea una nueva instancia de este tipo. developer.apple.com/swift/blog/?id=10 Entonces, obviamente, no puede modificar los campos / propiedades del lettipo de valor enlazado.
Krzak

15

letse usa para definir constantes y varpara definir variables.


7

Tal vez sea mejor establecer esta diferencia mediante la noción de Mutabilidad / Inmutabilidad que es el paradigma correcto de valores y la capacidad de cambio de instancias en el espacio Objetos que es más grande que las únicas nociones habituales "constantes / variables". Y además, esto está más cerca del enfoque del Objetivo C.

2 tipos de datos: tipo de valor y tipo de referencia.

En el contexto de los Tipos de valor:

'let' define un valor constante (indomable). 'var' define un valor modificable (mutable).

let aInt = 1   //< aInt is not changeable

var aInt = 1   //< aInt can be changed

En el contexto de los Tipos de referencia:

La etiqueta de un dato no es el valor sino la referencia a un valor.

if aPerson = Person (nombre: Foo, primero: Bar)

aPerson no contiene los datos de esta persona, sino la referencia a los datos de esta persona.

let aPerson = Person(name:Foo, first:Bar)
               //< data of aPerson are changeable, not the reference

var aPerson = Person(name:Foo, first:Bar)
               //< both reference and data are changeable.

eg:
var aPersonA = Person(name:A, first: a)
var aPersonB = Person(name:B, first: b)

aPersonA = aPersonB

aPersonA now refers to Person(name:B, first: b)

1
pero si aPersontiene setters podría modificar sus propiedades ¿verdad? entonces el letno hace lo Personinmutable.
2014

44
¿Inmutabilidad? Eso es imposible! Ciertamente antiadvisible. Creo que tu palabra que estás buscando puede ser "inmutabilidad" :-)
paxdiablo

6

los

La sección Declaración de constantes y variables de la documentación del lenguaje de programación Swift especifica lo siguiente:

Declaras constantes con la palabra clave let y variables con la palabra clave var.

Asegúrese de comprender cómo funciona esto para los tipos de referencia. A diferencia de los tipos de valor, las propiedades subyacentes del objeto pueden cambiar a pesar de que una instancia de un tipo de referencia se declare como una constante. Consulte la sección Las clases son tipos de referencia de la documentación y observe el ejemplo en el que cambian la propiedad frameRate.


5

Muy simple:

  • let es constante
  • var Es dinámico.

Poco de descripción:

letcrea una constante (algo así como un NSString). No puede cambiar su valor una vez que lo haya configurado. Sin embargo, aún puede agregarlo a otras cosas y crear nuevas variables.

varcrea una variable (algo así como NSMutableString) para que pueda cambiar el valor de la misma. Pero esto ha sido respondido varias veces.


4

letdefine una "constante". Su valor se establece una vez y solo una vez, aunque no necesariamente cuando lo declara. Por ejemplo, usted usa letpara definir una propiedad en una clase que debe establecerse durante la inicialización:

class Person {

    let firstName: String
    let lastName: String

    init(first: String, last: String) {
         firstName = first
         lastName = last
         super.init()
    }
}

Con esta configuración, no es válido asignar firstNameo lastNamedespués de llamar (por ejemplo) Person(first:"Malcolm", last:"Reynolds")para crear unPerson instancia.

Usted debe definir un tipo para todas las variables ( leto var) en tiempo de compilación, y cualquier código que intenta establecer una variable sólo podrán utilizar ese tipo (o un subtipo). Puede asignar un valor en tiempo de ejecución, pero su tipo debe ser conocido en tiempo de compilación.


4

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 que se establece, mientras que a variablese puede establecer en un valor diferente en el futuro.

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

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

Valor y tipo de referencia [Acerca de]

Valor (estructura, enumeración)

Swift structpuede cambiar su estado de mutabilidad:

let+ struct= immutable= Constante de valor
Puede no ser reasignado o cambió

var+ struct= mutable
Se puede reasignar o cambiar

Tipo de referencia (clase)

Los veloces classesson mutableun priorato

let+ class= Constante de dirección
Puede no ser reasignado y puede ser cambiado

var+ class
Se puede reasignar o cambiar

//STRUCT
  //let + struct
let letStructA = StructA()

    //change FAIL
letStructA.a = 5 //Compile ERROR: Cannot assign to property: 'structALet' is a 'let' constant

    //reassign FAIL
letStructA = StructA() // Compile ERROR: Cannot assign to value: 'structALet' is a 'let' constant

  //var + struct
var varStructA = StructA()

    //change OK
varStructA.a = 5

    //reassign OK
varStructA = StructA()

//CLASS
  //let + class
let letClassA = ClassA()

    //change OK
letClassA.a = 5

    //reassign FAIL
letClassA = ClassA() // Compile ERROR: Cannot assign to value: 'classALet' is a 'let' constant

  //var + class
var varClassA = ClassA()

    //change OK
varClassA.a = 5

    //reassign OK
varClassA = ClassA()

mutating - Funciones de estructura mutante

Puede marcar el método de una estructura comomutating

  1. Indica que esta función cambia los valores de propiedad internos.
  2. Solo se puede usar en var+struct
public struct StructA {
    public var a = 0

    public init() {}

    //func foo() { //Compile ERROR: Cannot assign to property: 'self' is immutable
    mutating func foo() {
        a = 5
    }
}

inout Modificar estructura dentro de una función

Puede marcar el parámetro de una función (que es struct) como inout

Dado que es structun tipo de valor, se pasa por valor como resultado, la función recuperará una copia. Si marca un parámetro structcomo inout, significa que este parámetro se convierte vary puede cambiar un estado de structy estos cambios serán visibles fuera del alcance de la función

//func foo(myStruct: StructA) { //Compile ERROR: line - myStruct.a = 10: Cannot assign to property: 's' is a 'let' constant
func foo(myStruct: inout StructA) {
    myStruct.a = 10
}

//using
//foo(myStruct: &letStructA) // Compile EROOR: Cannot pass immutable value as inout argument: 'letStructA' is a 'let' constant
foo(myStruct: &varStructA)

Úselo letsiempre que pueda. Úselo varcuando sea necesario.


2

Una diferencia más, que he encontrado en otros idiomas para las constantes es: no se puede inicializar la constante (let) para más adelante , se debe inicializar cuando esté a punto de declarar la constante.

Por ejemplo :

let constantValue : Int // Compile error - let declarations require an initialiser expression

Variable

var variableValue : Int // No issues 

2

letse usa para declarar un valor constante; no lo cambiará después de darle un valor inicial.
varse utiliza para declarar un valor variable; puede cambiar su valor como lo desee.


1

let se usa para definir constantes y var para definir variables. Usted define la cadena usando var, entonces una cadena particular puede modificarse (o mutarse) asignándola a una variable (en cuyo caso puede modificarse), y si define la cadena usando deje que sea una constante (en cuyo caso no puede ser modificado):

var variableString = "Apple"
variableString += " and Banana"
// variableString is now "Apple and Banana"

let constantString = "Apple"
constantString += " and another Banana"
// this reports a compile-time error - a constant string cannot be modified

0

dejar palabra clave define una constante

let myNum = 7

entonces myNum no se puede cambiar después;

Pero var define una variable ordinaria.

No es necesario conocer el valor de una constante en tiempo de compilación, pero debe asignarle un valor exactamente una vez.

Puede usar casi cualquier carácter que desee para nombres constantes y variables, incluidos los caracteres Unicode;

p.ej

var x = 7 // here x is instantiated with 7 
x = 99 // now x is 99 it means it has been changed.

Pero si tomamos let entonces ...

let x = 7 // here also x is instantiated with 7 
x = 99 // this will a compile time error

0

Como Luc-Oliver, NullData y algunos otros han dicho aquí, letdefine datos inmutables mientras vardefine datos mutables. Cualquiera funcque se pueda invocar en la variable que está marcada mutatingsolo se puede invocar si es una varvariable (el compilador arrojará un error). Esto también se aplica a funclos que toman una inoutvariable.

Sin embargo, lety vartambién significa que la variable no se puede reasignar. Tiene dos significados, ambos con propósitos muy similares.


0

El valor var se puede cambiar, después de inicializar. Pero dejar que el valor no se cambie cuando se intiliza una vez.

En caso de var

  function variable() {
     var number = 5, number = 6;
     console.log(number); // return console value is 6
   }
   variable();

En caso de dejar

   function abc() {
      let number = 5, number = 6;
      console.log(number); // TypeError: redeclaration of let number
   }
   abc();

Pero dejar que el valor no se cambie cuando se intiliza una vez. Yo no estoy de acuerdo con esto. Su comentario está bien con valores no objeto como int, float. Pero intente con una matriz mutable y una cadena mutable. Puede cambiar sus valores agregando o agregando valores. Lo correcto es dejar que los objetos no se puedan cambiar por su puntero, su dirección de puntero siempre será la misma, es por eso que se está reiniciando el error. Entonces puede decir que let hace un puntero constante que no se puede cambiar en el futuro.
TheTiger

No hay console.log en Swift. Verifique la etiqueta del OP
Dan Beaulieu

0

La palabra clave var se usa para definir una variable cuyo valor puede cambiar fácilmente de esta manera:

var no1 = 1 // declaring the variable 
no1 = 2 // changing the value since it is defined as a variable not a constant

Sin embargo, la palabra clave let es solo para crear una constante utilizada cuando no desea cambiar el valor de la constante nuevamente. Si intentara cambiar el valor de la constante, obtendrá un error:

let no2 = 5 // declaring no2 as a constant
no2 = 8 // this will give an error as you cannot change the value of a constant 

0

Let es una variable inmutable, lo que significa que no se puede cambiar, otros idiomas llaman a esto una constante. En C ++ puede definirlo como constante.

Var es una variable mutable, lo que significa que se puede cambiar. En C ++ (actualización de la versión 2011), es lo mismo que usar auto, aunque swift permite una mayor flexibilidad en el uso. Este es el tipo de variable más conocido para principiantes.


0

let es un valor constante, por lo que nunca se puede cambiar.

let number = 5  
number = 6               //This will not compile.

Var es una variable y puede cambiar (pero después de que se define no a un tipo de datos diferente).

var number = 5
number = 6               //This will compile.

Si intenta cambiar la variable a un tipo de datos diferente, no funcionará

var number = 5
number = "Hello World"   //This will not compile.

1
Let debería ser let .
TheTiger

0

La principal diferencia es que el varvalor variable puede cambiar y letno puede. Si desea tener datos de entrada del usuario, lo usaría varpara que el valor se pueda cambiar y use la letvariable de tipo de datos para que el valor no se pueda cambiar.

var str      = "dog"  // str value is "dog"
str          = "cat"  // str value is now "cat"

let strAnimal = "dog" // strAnimal value is "dog"
strAnimal     = "cat" // Error !

Let and Var no funciona utilizando (let y var) en letra minúscula.
Abhishek

0

Se puede reasignar un valor en caso de var

 //Variables
 var age = 42
 println(age) //Will print 42
 age = 90
 println(age) //Will Print 90

** la constante newAge no se puede reasignar a un nuevo valor. Intentar hacerlo generará un error de tiempo de compilación **

//Constants
let newAge = 92 //Declaring a constant using let
println(newAge) //Will print 92.


0

var es variable y puede cambiarse tantas veces como desee y siempre

por ejemplo

var changeit:Int=1
changeit=2
 //changeit has changed to 2 

let es constante y no se puede cambiar

por ejemplo

let changeit:Int=1
changeit=2
 //Error becuase constant cannot be changed

0

Aunque ya tiene muchas diferencias entre let y var, pero una diferencia principal es:

let is compiled fast in comparison to var.

-1

Todo el mundo ha respondido esto, pero aquí hay una manera de recordar qué es qué

Digamos siempre lo mismo piensa en "let" como dejar que esto funcione por una vez y siempre como para "var" las variables siempre pueden cambiar, por lo tanto, se llaman variables


-1

varEs la única forma de crear variables en Swift. varno significa variable dinámica como en el caso de lenguajes interpretados como javascript. Por ejemplo,

var name = "Bob"

En este caso, el tipo de variable namese infiere que el nombre es de tipo String, también podemos crear variables definiendo explícitamente el tipo, por ejemplo

var age:Int = 20

Ahora, si asigna una cadena a la edad, el compilador da el error.

letse usa para declarar constantes. Por ejemplo

let city = "Kathmandu"

O también podemos hacer,

let city:String = "Kathmandu"

Si intenta cambiar el valor de city, da error en tiempo de compilación.


-1

let se usa para constantes que no se pueden modificar mientras var es una variable ordinaria

Ejemplo:

let name = "Bob" Algo como name = "Jim" arrojará un error ya que no se puede modificar una constante.


-1

DIFERENCIA SIMPLE

let = (no se puede cambiar)

var = (actualización en cualquier momento)


1
Esto parece ser solo una repetición de muchas de las respuestas existentes.
Pang

-1

Fuente: https://thenucleargeeks.com/2019/04/10/swift-let-vs-var/

Cuando declaras una variable con var, significa que se puede actualizar, es variable, su valor se puede modificar.

Cuando declaras una variable con let, significa que no se puede actualizar, no es variable, su valor no se puede modificar.

var a = 1 
print (a) // output 1
a = 2
print (a) // output 2

let b = 4
print (b) // output 4
b = 5 // error "Cannot assign to value: 'b' is a 'let' constant"

Comprendamos el ejemplo anterior: hemos creado una nueva variable "a" con "palabra clave var" y hemos asignado el valor "1". Cuando imprimo "a" obtengo la salida como 1. Luego asigno 2 a "var a", es decir, estoy modificando el valor de la variable "a". Puedo hacerlo sin obtener el error del compilador porque lo declaró como var.

En el segundo escenario, creé una nueva variable "b" con "let keyword" y asigné el valor "4". Cuando imprimo "b" obtuve 4 como salida. Luego trato de asignar 5 a "let b", es decir, estoy tratando de modificar la variable "let" y aparece el error de tiempo de compilación "No se puede asignar al valor: 'b' es una constante 'let'".


-3

Aunque actualmente todavía estoy leyendo el manual, pero creo que esto está muy cerca del constpuntero C / C ++ . En otras palabras, algo así como la diferencia entre char const*y char*. El compilador también se niega a actualizar el contenido, no solo la reasignación de referencia (puntero).

Por ejemplo, supongamos que tiene esta estructura. Tenga cuidado de que esto sea una estructura, no una clase. AFAIK, las clases no tienen un concepto de estado inmutable.

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

Debido a que las estructuras son inmutables por defecto, debe marcar un método mutador con mutating. Y debido a que el nombre aaa1es constante, no se puede llamar a ningún método mutador. Esto es exactamente lo que esperábamos en los punteros C / C ++.

Creo que este es un mecanismo para admitir una especie de corrección constante .


-3

Declare constantes con la palabra clave let y variables con la palabra clave var.

let maximumNumberOfLoginAttempts = 10 var currentLoginAttempt = 0   
let maximumNumberOfLoginAttempts = 10
var currentLoginAttempt = 0

Declare constantes múltiples o variables múltiples en una sola línea, separadas por comas:

var x = 0.0, y = 0.0, z = 0.0

Impresión de constantes y variables

Puede imprimir el valor actual de una constante o variable con la función println:

println(friendlyWelcome)

Swift utiliza la interpolación de cadenas para incluir el nombre de una constante o variable como marcador de posición en una cadena más larga

Envuelva el nombre entre paréntesis y escape con una barra diagonal inversa antes del paréntesis de apertura:

println("The current value of friendlyWelcome is \(friendlyWelcome)")

Referencia: http://iosswift.com.au/?p=17


-4

Encontré una buena respuesta, espero que pueda ayudar :) ingrese la descripción de la imagen aquí


44
Esto es realmente incorrecto. letno significa que el objeto sea ​​inmutable, significa que el puntero es inmutable. Para obtener la funcionalidad equivalente en Obj-C, debe usar NSObject *const myObject = someobject;: las propiedades de dicho objeto se pueden modificar, pero el puntero myObjectno se puede modificar para que apunte a otro objeto.
SaltyNuts

1
Respuesta totalmente incorrecta. ¿Has probado con una matriz let: NSMutableArray = NSMutableArray () ?? Puede agregar y eliminar objetos a / de esto. let hace lo const pointerque no se puede cambiar en el futuro pero su valor sí se puede cambiar. No puede reiniciarlo, pero puede usarlo como desee.
TheTiger
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.