Qual é a diferença entre `let` e` var` in swift?


321

Qual é a diferença entre lete varno idioma Swift da Apple?

No meu entendimento, é uma linguagem compilada, mas não verifica o tipo no momento da compilação. Isso me deixa confuso. Como o compilador sabe sobre o erro de tipo? Se o compilador não verificar o tipo, não há um problema no ambiente de produção?


35
let é para constantes, var é para variáveis.
Collin Henderson

2
@ Edward O que você quer dizer com nenhuma verificação de tipo no tempo de compilação? Tanto quanto posso dizer, é estaticamente digitado, mas os tipos são inferidos se o compilador puder descobrir isso sozinho. Mas então eu só estou na página 25 ... ;-)
Joachim Isaksson

4
Isso está no tópico, mas é uma pergunta mal formulada. Existem pelo menos 2 questões (i) diff entre let e var ; (ii) digite safe vs type infer. Além disso, quando o pôster mencionou a fase de produção , ele realmente quis dizer em tempo de execução.
Kevin Le - Khnle

1
Além disso, var usado em variáveis ​​que definem coleções (matrizes e dicionário) cria uma coleção mutável (não apenas a referência, mas o conteúdo da coleção pode ser modificado.O outro uso de var é poder modificar os parâmetros passados ​​em uma função: func foo (var bar: Int) permitirá que você modificar o bar param localmente no âmbito função.
Laurent

Respostas:


407

A letpalavra-chave define uma constante:

let theAnswer = 42

O theAnswernão pode ser alterado depois. É por isso que qualquer coisa weaknão pode ser escrita usando let. Eles precisam mudar durante o tempo de execução e você deve estar usando var.

O vardefine uma variável comum.

O que é interessante:

O valor de uma constante não precisa ser conhecido em tempo de compilação , mas você deve atribuir o valor exatamente uma vez.

Outra característica estranha:

Você pode usar quase qualquer caractere que desejar para nomes constantes e variáveis, incluindo caracteres Unicode:

let 🐶🐮 = "dogcow"

Trechos de: Apple Inc. “A linguagem de programação Swift”. iBooks. https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewBook?id=881256329

EDITAR

Como comentários pedindo a adição de outros fatos à resposta, convertendo-os em respostas da wiki da comunidade . Sinta-se livre para editar a resposta para torná-la melhor.


1
C e C ++ também permitem identificadores Unicode, via UCNs. Se o compilador suportar qualquer codificação de origem Unicode, você poderá usar apenas os caracteres Unicode diretamente. Por exemplo, auto 🐶🐮 = "dogcow";funciona em C ++ para clang.
bames53

131
@ bames53 ok, só não tenho certeza do que quero depurar um programa como: if 😍 === 💝 { 💔 = ♠︎ }:);)
jm666

Aplica-se ao REPL? Porque você pode reatribuir a constante no REPL.
Ahmed Al Hafoudh

1
Primeiro, como observado acima, isso é totalmente diferente no REPL. Segundo, se é uma constante, não é muita coisa. Isso funciona muito bem no compilador: let foo = [1,2,3]; foo [2] = 5; println ("(foo)") // [1, 2, 5]
Kevin Frost

31
Esta resposta, embora a mais votada, não contém nenhuma menção de como let / var se comporta ao se referir a objetos em vez de tipos de valor. A chave é que, nos dois casos, você ainda pode alterar as propriedades do objeto, mas não pode modificar o ponteiro para se referir a outro objeto. Isso não é imediatamente óbvio nos exemplos básicos que envolvem números inteiros e seqüências de caracteres.
SaltyNuts

33

De acordo com o Swift Programming Language Book

Como C, Swift usa variáveis ​​para armazenar e se referir a valores por um nome de identificação. Swift também faz uso extensivo de variáveis ​​cujos valores não podem ser alterados. São conhecidas como constantes e são muito mais poderosas que as constantes em C.

Ambas vare letsão referências , portantolet é uma referência const . O uso de tipos fundamentais não mostra realmente como leté diferente const. A diferença ocorre ao usá-lo com instâncias de classe (tipos de referência):

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 terminologia está totalmente errada ... Todas as referências são de fato const. Não há conceito de "const ref". Uma vez vinculada, uma referência é sempre limitada ao mesmo endereço de memória e não pode ser alterada ou "não assentada". Eu acredito que você média var é um "ponteiro" e deixar que é um "ponteiro const"
AyBayBay

@AyBayBay Enquanto o que você está escrevendo está correto, por exemplo, em C ++, acho que o trecho acima prova, que não é o caso no Swift. Os ponteiros permitiriam acesso aritmético e direto à memória do ponteiro, o que novamente não é o caso aqui. - Edit: Eu não encontrei nenhuma evidência de que Todas as referências são de fato const const, é verdade para toda linguagem de programação.
Krzak 20/05

BTW de acordo com a Wikipedia ponteiros são referências
krzak

2
Concordo que sua terminologia está errada. vare letnão tem nada a ver com o fato de o identificador vinculado ser ou não uma referência. Se o tipo é um structtipo, é conceitualmente um valor. Se o tipo é um class, conceitualmente é uma referência e a referência é uma constante se letfor usada. Se CTestfosse uma estrutura, nenhuma de suas letTesttarefas funcionaria.
JeremyP

1
Se o tipo é um structtipo de valor, não há nada conceitual sobre ele. O mesmo com class- tipo de referência. Ao modificar um tipo de valor, você cria uma nova instância desse tipo. developer.apple.com/swift/blog/?id=10 Portanto, obviamente, você não pode modificar campos / propriedades do lettipo vinculado ao valor.
Krzak

15

leté usado para definir constantes e varpara definir variáveis.


7

Talvez seja melhor declarar essa diferença pela noção de Mutabilidade / Imutabilidade, que é o paradigma correto de mutabilidade de valores e instâncias no espaço Objetos, que é maior que as únicas noções "constantes / variáveis" habituais. Além disso, isso está mais próximo da abordagem do Objetivo C.

2 tipos de dados: tipo de valor e tipo de referência.

No contexto de tipos de valor:

'let' define um valor constante (indomável). 'var' define um valor mutável (mutável).

let aInt = 1   //< aInt is not changeable

var aInt = 1   //< aInt can be changed

No contexto de tipos de referência:

O rótulo de um dado não é o valor, mas a referência a um valor.

if aPerson = Person (nome: Foo, primeiro: Bar)

aPerson não contém os dados desta pessoa, mas a referência aos dados desta pessoa.

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
mas se aPersontiver setters você pode modificar suas propriedades certo? então o letnão torna o Personimutável.
drewish

4
Imutabilidade? Isso é impossível! Certamente antiadvisível. Eu acho que a palavra que você está procurando pode ser "imutabilidade" :-) #
315

6

o

A seção Declarantes de constantes e variáveis da documentação da linguagem de programação Swift especifica o seguinte:

Você declara constantes com a palavra-chave let e variáveis ​​com a palavra-chave var.

Certifique-se de entender como isso funciona para os tipos de referência. Diferentemente dos Tipos de Valor, as propriedades subjacentes do objeto podem mudar, apesar de uma instância de um tipo de referência ser declarada como constante. Consulte a seção Classes são tipos de referência da documentação e veja o exemplo em que eles alteram a propriedade frameRate.


5

Muito simples:

  • let é constante.
  • var é dinâmico.

Bocado da descrição:

letcria uma constante. (mais ou menos como um NSString). Você não pode alterar seu valor depois de defini-lo. Você ainda pode adicioná-lo a outras coisas e criar novas variáveis.

varcria uma variável (mais ou menos como NSMutableString) para que você possa alterar o valor. Mas isso foi respondido várias vezes.


4

letdefine uma "constante". Seu valor é definido uma vez e apenas uma vez, embora não necessariamente quando você o declara. Por exemplo, você letpode definir uma propriedade em uma classe que deve ser definida durante a inicialização:

class Person {

    let firstName: String
    let lastName: String

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

Com esta configuração, é inválido atribuir a firstNameou lastNameapós chamar (por exemplo) Person(first:"Malcolm", last:"Reynolds")para criar uma Personinstância.

Você deve definir um tipo para todas as variáveis ​​( letou var) em tempo de compilação, e qualquer código que tente definir uma variável pode usar apenas esse tipo (ou um subtipo). Você pode atribuir um valor no tempo de execução, mas seu tipo deve ser conhecido no tempo de compilação.


4

let- constant
var-variable

[Constante vs variável]
[Estrutural vs Classe]

O documento oficial docs.swift.org diz

O valor de a constantnão pode ser alterado depois de definido, enquanto a variablepode ser definido com um valor diferente no futuro.

Essa terminologia realmente descreve um mecanismo de reatribuição

Mutabilidade - mutável - o estado do objeto pode ser alterado após a criação

Valor e tipo de referência [Sobre]

Valor (Struct, Enum)

Os Swift structpodem alterar seu status de mutabilidade:

let+ struct= immutable= Constante de valor
Pode não ser reatribuído ou alterado

var+ struct= mutable
Pode ser reatribuído ou alterado

Tipo de referência (classe)

Swift's classessão mutableum priorado

let+ class= Constante de endereço
Ele pode não ser transferido e pode ser alterado

var+ class
Pode ser reatribuído ou alterado

//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 - Funções de mutação do Struct

Você pode marcar o método de uma estrutura comomutating

  1. Indica que esta função altera os valores internos da propriedade.
  2. Só pode ser usado em 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 Modificando struct dentro de uma função

Você pode marcar o parâmetro de uma função (que é struct) como inout

Como structum tipo de valor, ele é passado por valor, pois a função de resultado recuperará uma cópia. Se você marcar um parâmetro structcomo inout, significa que esse parâmetro se tornará vare você poderá alterar um estado structe essas alterações serão visíveis fora do escopo da função

//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)

Use letsempre que puder. Use varquando você precisar.


2

Mais uma diferença, que encontrei em outros idiomas para Constantes, é: não é possível inicializar a constante (let) para mais tarde , deve inicializar quando você estiver prestes a declarar a constante.

Por exemplo :

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

Variável

var variableValue : Int // No issues 

2

leté usado para declarar um valor constante - você não o alterará depois de atribuir um valor inicial.
varé usado para declarar um valor variável - você pode alterá-lo conforme desejar.


1

let é usado para definir constantes e var para definir variáveis. Você define a string usando var, então String específica pode ser modificada (ou mutada) atribuindo-a a uma variável (nesse caso, pode ser modificada) e, se você definir a string usando deixe que seja uma constante (nesse caso, não poderá 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

deixe a palavra-chave define uma constante

let myNum = 7

então myNum não pode ser alterado depois;

Mas var define uma variável comum.

O valor de uma constante não precisa ser conhecido em tempo de compilação, mas você deve atribuir um valor exatamente uma vez.

Você pode usar quase qualquer caractere que desejar para nomes constantes e variáveis, incluindo caracteres Unicode;

por exemplo

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

Mas se tomarmos deixe então ...

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

0

Como Luc-Oliver, NullData e alguns outros já disseram aqui, letdefine dados imutáveis ​​enquanto vardefine dados mutáveis. Qualquer um funcque possa ser chamado na variável marcada mutatingsó poderá ser chamado se for uma varvariável (o compilador lançará um erro). Isso também se aplica aos funcque recebem uma inoutvariável.

No entanto, lete vartambém significa que a variável não pode ser reatribuída. Tem dois significados, ambos com finalidades muito semelhantes


0

O valor var pode ser alterado após a inicialização. Mas deixe o valor não ser alterado, quando for fertilizar uma vez.

Em caso de var

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

Em caso de deixar

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

Mas deixe o valor não ser alterado, quando for fertilizar uma vez. Eu não concordo com isto. Seu comentário é bom com valores que não são objetos, como int, float. Mas tente com uma matriz mutável e uma sequência mutável. Você pode alterar seus valores adicionando ou anexando valores. O correto é permitir que os objetos não possam ser alterados pelo ponteiro; o endereço do ponteiro será sempre o mesmo, por isso você está recebendo um erro de reinicialização. Então você pode dizer que vamos fazer const ponteiro que não pode ser alterado no futuro.
TheTiger

Não há console.log no Swift. Verifique a tag do OP
Dan Beaulieu

0

A palavra-chave var é usada para definir uma variável cujo valor você pode alterar facilmente assim:

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

No entanto, a palavra-chave let é apenas para criar uma constante usada quando você não deseja alterar o valor da constante novamente. Se você tentar alterar o valor da constante, receberá um erro:

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 é uma variável imutável, o que significa que não pode ser alterado; outros idiomas chamam isso de constante. Em C ++, você pode defini-lo como const.

Var é uma variável mutável, o que significa que pode ser alterada. No C ++ (atualização de versão de 2011), é o mesmo que usar auto, embora o swift permita mais flexibilidade no uso. Este é o tipo de variável mais conhecido para iniciantes.


0

let é um valor constante, portanto nunca pode ser alterado.

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

Var é uma variável e pode ser alterada (mas depois de definida não para um tipo de dados diferente).

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

Se você tentar alterar a variável para um dataType diferente, ela não funcionará

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

1
Let deve ser deixado .
TheTiger

0

A principal diferença é que o varvalor da variável pode mudar e letnão pode. Se você deseja ter dados de entrada do usuário, use varpara que o valor possa ser alterado e use a letvariável de tipo de dados para que o valor não possa ser alterado.

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 e ​​Var não está funcionando usando (let e var) em letra minúscula.
Abhishek 25/03

0

Um valor pode ser reatribuído no caso de var

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

** a constante newAge não pode ser reatribuída para um novo valor. Tentar fazer isso resultará em um erro de tempo de compilação **

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


0

var é variável que pode ser alterada quantas vezes você quiser e sempre

por exemplo

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

let é constante que não pode ser alterado

por exemplo

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

0

Mesmo que você já tenha muitas diferenças entre let e var, uma diferença principal é:

let is compiled fast in comparison to var.

-1

Todo mundo já respondeu isso, mas aqui está uma maneira de você lembrar o que é o que

Let sempre diz o mesmo pensamento de "let", pois deixe isso funcionar pela primeira vez e sempre como para "var" as variáveis ​​sempre podem mudar, portanto, sendo chamadas de variáveis


-1

varé a única maneira de criar uma variável rapidamente. varnão significa variável dinâmica como no caso de linguagens interpretadas como javascript. Por exemplo,

var name = "Bob"

Nesse caso, o tipo de variável nameé inferido de que nome é do tipo String, também podemos criar variáveis ​​definindo explicitamente o tipo, por exemplo

var age:Int = 20

Agora, se você atribuir uma string a idade, o compilador fornecerá o erro.

leté usado para declarar constantes. Por exemplo

let city = "Kathmandu"

Ou também podemos fazer,

let city:String = "Kathmandu"

Se você tentar alterar o valor da cidade, ocorrerá um erro no momento da compilação.


-1

let é usado para constantes que não podem ser modificadas enquanto var é uma variável comum

Exemplo:

let name = "Bob" Algo como name = "Jim" gera um erro, pois uma constante não pode ser modificada.


-1

DIFERENÇA SIMPLES

let = (não pode ser alterado)

var = (qualquer atualização a qualquer momento)


1
Isso parece ser apenas uma repetição de muitas das respostas existentes.
Pang

-1

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

Quando você declara uma variável com var, significa que ela pode ser atualizada, é variável, seu valor pode ser modificado.

Quando você declara uma variável com let, significa que não pode ser atualizada, não é variável, seu valor não pode ser modificado.

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"

Vamos entender o exemplo acima: Criamos uma nova variável "a" com "var keyword" e atribuímos o valor "1". Quando imprimo "a", obtive a saída como 1. Então atribuo 2 a "var a", ou seja, estou modificando o valor da variável "a". Eu posso fazer isso sem obter erro do compilador porque o declarei como var.

No segundo cenário, criei uma nova variável "b" com "let keyword" e atribui o valor "4". Quando imprimo "b", obtive 4 como saída. Então, tento atribuir 5 a “let b”, ou seja, estou tentando modificar a variável “let” e recebo o erro de tempo de compilação “Não é possível atribuir ao valor: 'b' é uma constante 'let'”.


-3

Embora atualmente ainda esteja lendo o manual, acho que isso está muito próximo do constponteiro C / C ++ . Em outras palavras, algo como a diferença entre char const*e char*. O compilador também se recusa a atualizar o conteúdo, não apenas a reatribuição de referência (ponteiro).

Por exemplo, digamos que você tenha essa estrutura. Tome cuidado para que isso seja uma estrutura, não uma classe. AFAIK, as classes não têm um conceito de estado imutável.

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

Como as estruturas são imutáveis ​​por padrão, você precisa marcar um método mutador mutating. E como o nome aaa1é constante, você não pode chamar nenhum método mutador. Isso é exatamente o que esperávamos em ponteiros C / C ++.

Eu acredito que este é um mecanismo para suportar um tipo de material de correção constante .


-3

Declare constantes com a palavra-chave let e variáveis ​​com a palavra-chave var.

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

Declare várias constantes ou várias variáveis ​​em uma única linha, separadas por vírgulas:

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

Constantes e variáveis ​​de impressão

Você pode imprimir o valor atual de uma constante ou variável com a função println:

println(friendlyWelcome)

Swift usa interpolação de string para incluir o nome de uma constante ou variável como espaço reservado em uma string maior

Coloque o nome entre parênteses e escape com uma barra invertida antes do parêntese de abertura:

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

Referência: http://iosswift.com.au/?p=17


-4

Encontrou uma boa resposta espero que possa ajudar :) insira a descrição da imagem aqui


4
Isso está realmente incorreto. letnão significa que o objeto é imutável, significa que o ponteiro é imutável. Para obter a funcionalidade equivalente no Obj-C, você precisa usar NSObject *const myObject = someobject;- As propriedades desse objeto podem ser modificadas, mas o ponteiro myObjectnão pode ser modificado para apontar para outro objeto.
SaltyNuts

1
Resposta totalmente errada. Você já tentou com uma matriz let: NSMutableArray = NSMutableArray () ?? Você pode adicionar e remover objetos para isso. deixe marcas const pointerque não podem ser mudadas no futuro, mas seu valor pode ser. Você não pode reinicializar, mas pode usá-lo como quiser.
TheTiger
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.