В чем разница между `let` и` var` в swift?

321

В чем разница между letи varв Swift языке Apple?

В моем понимании это компилируемый язык, но он не проверяет тип во время компиляции. Это меня смущает. Как компилятор узнает об ошибке типа? Если компилятор не проверяет тип, это не проблема с производственной средой?

Эдвард
источник
35
let для констант, var для переменных.
Коллин Хендерсон
2
@ Эдвард Что вы подразумеваете под отсутствием проверки типов во время компиляции? Насколько я могу судить, он статически типизирован, но типы выводятся, если компилятор сам это выяснит. Но тогда я только на странице 25 ... ;-)
Иоахим Исакссон
4
Это по теме, но плохо сформулированный вопрос. Есть как минимум 2 вопроса: (i) diff между let и var ; (II) тип сейф против типа логического вывода. Кроме того, когда на плакате упоминается этап производства , он действительно имел в виду время выполнения.
Кевин Ле - Khnle
1
Кроме того, var, используемый для переменных, которые определяют коллекции (массивы и словарь), создает изменяемую коллекцию (можно изменять не только ссылку, но и содержимое коллекции. Другое использование var - возможность изменять параметры, передаваемые в функцию: func foo (var bar: Int) позволит вам изменять панель параметров локально в области действия функции
Laurent
возможный дубликат Difrentiate let и var в языке программирования Swift
Парамагнитный круассан

Ответы:

407

letКлючевое слово определяет константу:

let theAnswer = 42

Не theAnswerможет быть изменено впоследствии. Вот почему ничего weakнельзя написать с помощью let. Они должны измениться во время выполнения, и вы должны использовать varвместо этого.

varОпределяет обычную переменную.

Что интересно:

Значение константы не нужно знать во время компиляции , но вы должны назначить значение ровно один раз.

Еще одна странная особенность:

Вы можете использовать практически любой символ, который вам нравится, для имен констант и переменных, включая символы Unicode:

let 🐶🐮 = "dogcow"

Выдержки из: Apple Inc. «Язык программирования Swift». интерактивные книги. https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewBook?id=881256329

РЕДАКТИРОВАТЬ

Потому что комментарии просят добавить другие факты к ответу, преобразовывая это в ответ сообщества вики . Не стесняйтесь редактировать ответ, чтобы сделать его лучше.

jm666
источник
1
C и C ++ также позволяют идентификаторы Unicode через UCN. Если компилятор поддерживает любую исходную кодировку Unicode, то вы можете просто использовать символы Unicode напрямую. Например auto 🐶🐮 = "dogcow";работает в C ++ для Clang.
bames53
131
@ bames53 хорошо, я только не уверен, чем хочу отладить такую ​​программу, как: if 😍 === 💝 { 💔 = ♠︎ }:);)
jm666
Это относится к REPL? Потому что вы можете переназначить константу в REPL.
Ахмед Аль-Хафуд,
1
Во-первых, как отмечалось выше, в REPL все совершенно иначе. Во-вторых, если это константа, это не так много. Это прекрасно работает в компиляторе: let foo = [1,2,3]; foo [2] = 5; println ("(foo)") // [1, 2, 5]
Кевин Фрост
31
Этот ответ, хотя и пользуется наибольшим спросом, не содержит упоминаний о том, как ведет себя / var при обращении к объектам вместо типов значений. Ключ в том, что в обоих случаях вы все еще можете изменить свойства объекта, но не можете изменить указатель для ссылки на другой объект. Это не сразу видно из базовых примеров с целыми числами и строками.
SaltyNuts
33

Согласно Книге языков программирования Swift

Как и C, Swift использует переменные для хранения и обращения к значениям по идентифицирующему имени. Swift также широко использует переменные, значения которых не могут быть изменены. Они известны как константы, и они намного мощнее, чем константы в C.

Оба varи letявляются ссылками , поэтому letявляется константной ссылкой . Использование фундаментальных типов на самом деле не показывает, letчем отличается const. Разница возникает при использовании его с экземплярами классов (ссылочными типами):

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
источник
1
Эта терминология совершенно неверна ... Все ссылки действительно являются ссылками на константы Не существует понятия «const ref». После привязки ссылка всегда привязывается к одному и тому же адресу памяти и не может быть изменена или «неактивна». Я полагаю, вы имеете в виду, что var - это «указатель», а пусть это «постоянный указатель»
AyBayBay
@AyBayBay Хотя то, что вы пишете, верно, например, в C ++, я думаю, что приведенный выше фрагмент кода доказывает, что в Swift дело обстоит иначе. Указатели позволят арифметику указателей и прямой доступ к памяти, что опять-таки здесь не так. - Изменить: я не нашел доказательств того, что все ссылки действительно являются константными ссылками, это верно для каждого языка программирования.
Крзак
Кстати, согласно Википедии указатели являются ссылками
Кржак
2
Я согласен, что ваша терминология неверна. varи не letимеют никакого отношения к тому, является ли привязываемый идентификатор ссылкой или нет. Если тип является structтипом, это концептуально значение. Если тип - classэто концептуально ссылка, а ссылка является константой, если letиспользуется. Если бы CTestбыла структура, ни одно из ваших letTestзаданий не сработало бы.
JeremyP
1
Если тип является типом structзначения, в этом нет ничего концептуального. То же самое с class- ссылочный тип. При изменении типа значения вы создаете новый экземпляр этого типа. developer.apple.com/swift/blog/?id=10 Очевидно, что вы не можете изменять поля / свойства, letсвязанные с типом значения.
Кржак
15

letиспользуется для определения констант и varопределения переменных.

atxe
источник
7

Возможно, лучше констатировать это различие понятием изменчивости / неизменности, которое является правильной парадигмой изменчивости значений и экземпляров в пространстве объектов, которая больше, чем единственные обычные понятия «постоянная / переменная». И, кроме того, это ближе к подходу Objective C.

2 типа данных: тип значения и тип ссылки.

В контексте типов значений:

«let» определяет постоянное значение (не изменяемое). 'var' определяет изменяемое значение (изменяемое).

let aInt = 1   //< aInt is not changeable

var aInt = 1   //< aInt can be changed

В контексте типов ссылок:

Метка данных - это не значение, а ссылка на значение.

if aPerson = Person (имя: Foo, сначала: Bar)

aPerson не содержит Данные этого лица, но содержит ссылку на данные этого Лица.

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
но если aPersonесть сеттеры, вы могли бы изменить его свойства, верно? так что letне делает Personнеизменным.
drewish
4
Unmutability? Это невозможно! Конечно, не рекомендуется. Я думаю, что ваше слово, которое вы ищете, может быть "неизменность" :-)
paxdiablo
6

The

Объявление раздела « Константы и переменные » в документации по языку программирования Swift указывает следующее:

Вы объявляете константы с ключевым словом let, а переменные с ключевым словом var.

Убедитесь, что вы понимаете, как это работает для справочных типов. В отличие от типов значений, базовые свойства объекта могут изменяться, несмотря на то, что экземпляр ссылочного типа объявлен как константа. См. Раздел « Классы - ссылочные типы » документации и посмотрите на пример, где они изменяют свойство frameRate.

mr_sd
источник
5

Очень просто:

  • let постоянно.
  • var динамично

Бит описания:

letсоздает постоянную. (вроде как NSString). Вы не можете изменить его значение, как только вы его установили. Вы все еще можете добавить его к другим вещам и создать новые переменные.

varсоздает переменную. (вроде как NSMutableString), чтобы вы могли изменить его значение. Но на это ответили несколько раз.

Раджеш Логанатхан
источник
4

letопределяет «константу». Его значение устанавливается один раз и только один раз, хотя не обязательно, когда вы его объявляете. Например, вы используете letдля определения свойства в классе, которое должно быть установлено во время инициализации:

class Person {

    let firstName: String
    let lastName: String

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

При такой настройке недопустимо назначать firstNameили lastNameпосле вызова (например) Person(first:"Malcolm", last:"Reynolds")создать Personэкземпляр.

Вы должны определить тип для всех переменных ( letили var) во время компиляции, и любой код, который пытается установить переменную, может использовать только этот тип (или подтип). Вы можете присвоить значение во время выполнения, но его тип должен быть известен во время компиляции.

rickster
источник
4

let- constant
var-variable

[Константа против переменной]
[Структура против класса]

Официальный документ docs.swift.org говорит

Значение a constantне может быть изменено после его установки, тогда как a variableможет быть установлено на другое значение в будущем.

Эта терминология фактически описывает механизм переназначения

Изменчивость - изменяемая - состояние объекта может быть изменено после создания

Значение и тип ссылки [О программе]

Значение (структура, перечисление)

Swift structмогут изменить свой статус изменчивости:

let+ struct= immutable= Константа значение
может не быть переназначены или изменены

var+ struct= mutable
Может быть переназначен или изменен

Тип ссылки (класс)

Свифт classesявляются mutableа-априорным

let+ class= Константа адреса
может не быть переназначен и могут быть изменены

var+ class
Может быть переназначен или изменен

//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 - Функции Мутирующей Структуры

Вы можете пометить метод структуры какmutating

  1. Указывает, что эта функция изменяет значения внутренних свойств.
  2. Может использоваться только на 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 Модификация структуры внутри функции

Вы можете пометить параметр функции (который является структурой) как inout

Поскольку structтип значения, он передается по значению, так как в результате функция будет получать копию. Если вы пометите параметр structкак inoutпараметр, это означает, что этот параметр становится varи вы можете изменить состояние, structи эти изменения будут видны за пределами области действия функции.

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

Используйте, letкогда можете. Используйте, varкогда нужно.

yoAlex5
источник
2

Еще одно отличие, с которым я столкнулся в других языках для констант, заключается в следующем: не могу инициализировать константу (пусть) на потом , следует инициализировать, когда вы собираетесь объявить константу.

Например :

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

переменная

var variableValue : Int // No issues 
Кумар К.Л.
источник
2

letиспользуется для объявления постоянного значения - вы не измените его после задания начального значения.
varиспользуется для объявления значения переменной - вы можете изменить ее значение по своему желанию.

jabez128
источник
1

let используется для определения констант, а var для определения переменных. Вы определяете строкуиспользуя вар то конкретная строка может быть изменена (или мутантным), назначив его переменный (в этом случае оно может быть изменено), и если вы определили строкуиспользуя пусть свою константу (в этом случае она не может быть изменен):

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

ключевое слово let определяет константу

let myNum = 7

поэтому myNum не может быть изменен впоследствии;

Но var определяет обычную переменную.

Значение константы не нужно знать во время компиляции, но вы должны присвоить ей значение ровно один раз.

Вы можете использовать практически любой символ, который вам нравится, для имен констант и переменных, включая символы Юникода;

например

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

Но если мы возьмем пусть тогда ...

let x = 7 // here also x is instantiated with 7 
x = 99 // this will a compile time error
Мохит Томар
источник
0

Как и Luc-Oliver, NullData и некоторые другие уже сказали здесь, letопределяют неизменяемые данные, а varопределяют изменяемые данные. Все, funcчто может быть вызвано для помеченной переменной, mutatingможет быть вызвано, только если она является varпеременной (компилятор выдаст ошибку). Это также относится к тем func, которые принимают inoutпеременную.

Тем не менее, letи varтакже означает , что переменная не может быть переназначен. Это имеет два значения, оба с очень похожими целями

matrinox
источник
0

Значение var можно изменить после инициализации. Но пусть значение не изменится, когда его задействуют один раз.

В случае вар

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

В случае аренды

   function abc() {
      let number = 5, number = 6;
      console.log(number); // TypeError: redeclaration of let number
   }
   abc();
Абхишек
источник
Но пусть значение не изменится, когда его задействуют один раз. Я не согласен с этим. Ваш комментарий подходит для не объектных значений, таких как int, float. Но попробуйте с изменяемым массивом и изменяемой строкой. Вы можете изменить их значения, добавляя или добавляя значения. Правильным является то, что объекты не могут быть изменены по указателю, их адрес указателя всегда будет одинаковым, поэтому вы получаете ошибку повторной инициализации. Таким образом, вы можете сказать, что пусть делает константный указатель, который не может быть изменен в будущем.
TheTiger
В Swift нету console.log. Проверьте тег ОП
Дэн Болье,
0

Ключевое слово var используется для определения переменной, значение которой вы можете легко изменить следующим образом:

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

Однако ключевое слово let используется только для создания константы, используемой, когда вы не хотите снова изменять значение константы. Если вы попытаетесь изменить значение константы, вы получите ошибку:

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

Пусть является неизменной переменной, то есть ее нельзя изменить, другие языки называют ее константой. В C ++ это вы можете определить как const.

Var является изменяемой переменной, это означает, что она может быть изменена. В C ++ (обновление версии 2011) это то же самое, что и использование auto, хотя swift обеспечивает большую гибкость в использовании. Это более известный тип переменной для начинающих.

HS__HS
источник
0

let является постоянным значением, поэтому его нельзя изменить.

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

Var является переменной и может изменяться (но после того, как она определена не для другого типа данных.)

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

Если вы попытаетесь изменить переменную на другой тип данных, он не будет работать

var number = 5
number = "Hello World"   //This will not compile.
Марио Хименес
источник
1
Пусть должно быть пусть .
TheTiger
0

Основное отличие состоит в том, что varзначение переменной может меняться, а letне может. Если вы хотите, чтобы пользователь вводил данные, вы должны использовать его, varчтобы изменить значение, и использовать letпеременную типа данных, чтобы это значение нельзя было изменить.

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

let strAnimal = "dog" // strAnimal value is "dog"
strAnimal     = "cat" // Error !
Грег Девелопмент
источник
Пусть и Var не работает, используя (пусть и var) в маленькой букве.
Абхишек
0

Значение может быть переназначено в случае var

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

** константу newAge нельзя переназначить на новое значение. Попытка сделать это даст ошибку времени компиляции **

//Constants
let newAge = 92 //Declaring a constant using let
println(newAge) //Will print 92.
Дебасис Дас
источник
0

«Используйте let для создания константы и var для создания переменной»

Excerpt From: Apple Inc. “The Swift Programming Language.” iBooks. https://itun.es/us/jEUH0.l

zumzum
источник
0

var - это переменная, которую можно менять сколько угодно раз и когда угодно

например

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

пусть это константа, которая не может быть изменена

например

let changeit:Int=1
changeit=2
 //Error becuase constant cannot be changed
Субаш Чандру
источник
0

Хотя у вас уже есть много различий между let и var, но есть одно главное отличие:

let is compiled fast in comparison to var.
Вивек Тяги
источник
-1

Все в значительной степени ответили на это, но вот способ, которым вы можете вспомнить, что к чему

Пусть всегда будет говорить то же самое о «let», что и let, это работает на этот раз и всегда, как и для переменных «var», которые всегда могут меняться, поэтому их называют переменными

allen6131
источник
-1

varэто единственный способ создать переменную в Swift. varне означает динамическую переменную, как в случае интерпретируемых языков, таких как javascript. Например,

var name = "Bob"

В этом случае тип переменной nameподразумевается, что имя имеет тип String, мы также можем создавать переменные, явно определяя тип, например

var age:Int = 20

Теперь, если вы назначите строку возрасту, то компилятор выдаст ошибку.

letиспользуется для объявления констант. Например

let city = "Kathmandu"

Или мы также можем сделать,

let city:String = "Kathmandu"

Если вы попытаетесь изменить значение city, он выдаст ошибку во время компиляции.

Маной Карки
источник
-1

let используется для констант, которые нельзя изменить, тогда как var - обычная переменная

Пример:

let name = «Bob» Что-то вроде name = «Jim» выдаст ошибку, так как константа не может быть изменена.

alex2792
источник
-1

ПРОСТАЯ РАЗНИЦА

let = (не может быть изменено)

var = (обновление в любое время)

хамаюн зеб
источник
1
Похоже, это просто повторение многих из существующих ответов.
Пан
-1

Источник: https://thenucleargeeks.com/2019/04/10/swift-let-vs-var/

Когда вы объявляете переменную с помощью var, это означает, что она может быть обновлена, она является переменной, ее значение может быть изменено.

Когда вы объявляете переменную с помощью let, это означает, что она не может быть обновлена, она не является переменной, ее значение не может быть изменено.

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"

Давайте разберемся с приведенным выше примером: мы создали новую переменную «a» с «ключевым словом var» и присвоили значение «1». Когда я печатаю «a», я получаю вывод как 1. Затем я присваиваю 2 «var a», т.е. я изменяю значение переменной «a». Я могу сделать это без получения ошибки компилятора, потому что я объявил его как var.

Во втором сценарии я создал новую переменную «b» с «ключевым словом let» и присвоил значение «4». Когда я печатаю «b», я получаю 4 в качестве вывода. Затем я пытаюсь присвоить 5 «let b», т.е. я пытаюсь изменить переменную «let», и я получаю ошибку времени компиляции «Невозможно присвоить значение:« b »является константой« let »».

Адитья
источник
-3

Хотя в настоящее время я все еще читаю руководство, но я думаю, что это очень близко к constуказателю C / C ++ . Другими словами, что-то вроде разницы между char const*иchar* . Компилятор также отказывается обновлять содержимое, а не только переназначение ссылок (указатель).

Например, допустим, у вас есть эта структура. Позаботьтесь, что это структура, а не класс. AFAIK, у классов нет понятия неизменного состояния.

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

Поскольку структуры являются неизменяемыми по умолчанию, необходимо пометить метод мутатора с помощью mutating. И поскольку имя aaa1является константой, вы не можете вызвать какой-либо метод мутатора для него. Это именно то, что мы ожидали от указателей C / C ++.

Я полагаю, что это механизм для поддержки некоторой вещи с правильной константой .

Eonil
источник
-3

Объявите константы с ключевым словом let, а переменные с ключевым словом var.

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

Объявите несколько констант или несколько переменных в одной строке, разделенных запятыми:

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

Константы и переменные печати

Вы можете напечатать текущее значение константы или переменной с помощью функции println:

println(friendlyWelcome)

Swift использует строковую интерполяцию, чтобы включить имя константы или переменной в качестве заполнителя в более длинной строке

Оберните имя в круглых скобках и экранируйте его обратной косой чертой перед открывающей скобкой:

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

Ссылка: http://iosswift.com.au/?p=17

PatWoW
источник
-4

Нашел хороший ответ, надеюсь, это поможет :) введите описание изображения здесь

Noor
источник
4
Это на самом деле неверно. letне означает, что объект является неизменным, это означает, что указатель является неизменным. Чтобы получить эквивалентную функциональность в Obj-C, вам нужно использовать NSObject *const myObject = someobject;- Свойства такого объекта могут быть изменены, но указатель myObjectне может быть изменен, чтобы указывать на другой объект.
SaltyNuts
1
Совершенно неверный ответ. Вы пытались с массивом let: NSMutableArray = NSMutableArray () ?? Вы можете добавлять и удалять объекты в / из этого. пусть делает то, const pointerчто не может быть изменено в будущем, но его ценность может быть. Вы не можете повторно инициализировать его, но можете использовать его как хотите.
TheTiger