Яка різниця між `let` та` var` у швидкому?


321

Яка різниця між мовою Swift у Apple letі varу ній?

На моє розуміння, це компільована мова, але вона не перевіряє тип під час компіляції. Мене це бентежить. Як компілятор знає про помилку типу? Якщо компілятор не перевіряє тип, чи не проблема з виробничим середовищем?


35
нехай для констант, var - для змінних.
Колін Хендерсон

2
@Edward Що ви маєте на увазі, не перевіряючи тип під час компіляції? Наскільки я можу сказати, він набирається статично, але типи виводяться, якщо компілятор може розібратися в цьому сам. Але тоді я лише на сторінці 25 ... ;-)
Йоахім Ісакссон

4
Це на тему, але погано сформульоване питання. Є щонайменше 2 питання (i) різниться між let та var ; (ii) введіть безпечний та тип висновку. Крім того, коли плакат згадував етап виробництва , він справді мав на увазі час виконання.
Кевін Ле - Кнл

1
Крім того, var, який використовується для змінних, які визначають колекції (масиви та словник), створює колекцію, що змінюється (не тільки посилання, але вміст колекції можна змінювати. Інше використання var може змінювати параметри, передані у функції: func foo (var bar: Int) дозволить вам локально змінювати панель парам у межах функції.
Лоран

Відповіді:


407

letКлючове слово визначає константу:

let theAnswer = 42

Після theAnswerцього неможливо змінити. Ось чому нічого weakне можна записати, використовуючи let. Вони повинні змінюватися під час виконання, і ви повинні використовувати їх varзамість цього.

varВизначає звичайну змінну.

Що цікавого:

Значення константи не потрібно знати в час компіляції , але потрібно призначити значення рівно один раз.

Ще одна дивна особливість:

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

let 🐶🐮 = "dogcow"

Уривки: Apple Inc. "Мова швидкого програмування". iBooks. https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewBook?id=881256329

EDIT

Тому що коментарі просять додати інші факти до відповіді, перетворюючи це у відповідь вікі спільноти . Не соромтесь редагувати відповідь, щоб зробити її кращою.


1
C і C ++ дозволяє також ідентифікатори Unicode через UCN. Якщо компілятор підтримує будь-яке кодування джерела Unicode, ви можете просто використовувати символи Unicode безпосередньо. Наприклад, auto 🐶🐮 = "dogcow";працює в C ++ для clang.
bames53

131
@ bames53 Гаразд, я не впевнений, наскільки я хочу налагодити таку програму, як: if 😍 === 💝 { 💔 = ♠︎ }:);)
jm666

Чи застосовується це до REPL? Тому що ви можете перепризначити константу в REPL.
Ахмед Аль Хафуд

1
По-перше, як було зазначено вище, це є абсолютно різним у системі REPL. По-друге, якщо це константа, це не багато одного. Це добре працює в компіляторі: нехай foo = [1,2,3]; foo [2] = 5; println ("(foo)") // [1, 2, 5]
Кевін Фрост

31
Ця відповідь, хоч і є найбільш сприятливою, не містить жодної згадки про те, як let / var поводиться при посиланні на об'єкти замість типів значень. Ключовим є те, що в обох випадках ви все ще можете змінити властивості об'єкта, але не можете змінити вказівник на посилання на інший об’єкт. Це не відразу очевидно з основних прикладів, що містять цілі числа та рядки.
SaltyNuts

33

Відповідно до Книги мов програмування Свіфт

Як і C, Swift використовує змінні для зберігання та посилання на значення за допомогою ідентифікаційного імені. Swift також широко використовує змінні, значення яких неможливо змінити. Вони відомі як константи і значно потужніші, ніж константи в С.

І те, varі інше letє посиланням , тому letє посиланням на const . Використання основних типів насправді не показує, 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"

1
Ця термінологія є абсолютно помилковою ... Усі посилання справді є посиланнями, які є найпоширенішими. Не існує поняття "const ref". Після прив'язки посилання завжди обмежується однією і тією ж адресою пам’яті і не може бути змінене або «незакреслене». Я вважаю, що ви маєте на увазі, що var - це "покажчик", а нехай це "покажчик const"
AyBayBay

@AyBayBay Хоча те, що ви пишете, є правильним, наприклад, C ++, я думаю, що наведений вище фрагмент доводить, що у Swift це не так. Покажчики дозволять вказувати арифметичний і прямий доступ до пам’яті, що тут знову не так. - Редагувати: Я не знайшов жодних доказів того, що всі посилання справді є посиланнями const , справедливими для кожної мови програмування.
Крзак

BTW за вказівниками Вікіпедії - це посилання
Крзак

2
Я згоден, що ваша термінологія неправильна. varі не letмають нічого спільного з тим, чи пов'язаний ідентифікатор є посиланням чи ні. Якщо тип - це structтип, це концептуально значення. Якщо тип є a, classце концептуально посилання, а посилання є постійною, якщо letвикористовується. Якби це CTestбула структура, жодне з ваших letTestзавдань не працювало б.
JeremyP

1
Якщо тип a struct- це тип значення, у ньому немає нічого концептуального. Те саме з class- еталонним типом. Під час модифікації типу значення ви створюєте новий екземпляр цього типу. developer.apple.com/swift/blog/?id=10 Отже, очевидно, ви не можете змінювати поля / властивості, letприв'язані до типу значення.
Крзак

15

letвикористовується для визначення констант і varдля визначення змінних.


7

Можливо, краще вказати цю різницю за допомогою поняття Mutability / Unmutability, що є правильною парадигмою значень та змін змін екземплярів у просторі Об'єктів, яка є більшою, ніж єдині звичайні / постійні звичайні поняття. І крім того, це ближче до підходу Цілі С.

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

У контексті типів цінності:

'нехай' визначає постійне значення (нематеріальне). 'var' визначає змінне значення (змінне).

let aInt = 1   //< aInt is not changeable

var aInt = 1   //< aInt can be changed

У контексті довідкових типів:

Мітка даних - це не значення, а посилання на значення.

якщо aPerson = Особа (ім'я: 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непорушним.
Мальовничий

4
Незмінюваність? Це неможливо! Безумовно, не доцільно. Я думаю, що слово, яке ви шукаєте, може бути "
незмінним

6

The

У розділі Декларування констант і змінних документації щодо мови програмування Swift зазначено наступне:

Ви оголошуєте константи ключовим словом let та змінними за допомогою ключового слова var.

Не забудьте зрозуміти, як це працює для типів довідки. На відміну від типів значення, основні властивості об'єкта можуть змінюватися, незважаючи на те, що екземпляр опорного типу оголошується постійним. Дивіться розділ Класи - Довідкові типи документації та подивіться приклад, де вони змінюють властивість frameRate.


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) під час компіляції, і будь-який код, який намагається встановити змінну, може використовувати лише цей тип (або підтип). Ви можете призначити значення під час виконання, але його тип повинен бути відомий під час компіляції.


4

let- constant
var-variable

[Константа проти змінної]
[Структура проти класу]

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

Значення параметра constantнеможливо змінити після його встановлення, тоді як в variableмайбутньому можна встановити інше значення.

Ця термінологія фактично описує механізм перепризначення

Переміщення - змінне - стан об'єкта може бути змінено після створення

Значення та тип довідки [Про]

Значення (Struct, Enum)

Свіфт 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 - Функції мутації структури

Ви можете позначити метод struct як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коли потрібно.


2

Ще одна відмінність, з якою я стикався в інших мовах для констант, полягає в тому, що: не можу ініціалізувати константу (нехай) на потім , слід ініціалізувати, коли ви збираєтесь оголосити константу.

Наприклад :

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

Змінна

var variableValue : Int // No issues 

2

letвикористовується для оголошення постійного значення - ви не зміните його після надання початкового значення.
varвикористовується для оголошення змінної величини - ви можете змінити її значення за своїм бажанням.


1

Let використовується для визначення констант, а var для визначення змінних. Ви визначаєте рядок за допомогою 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 myNum = 7

тому myNum не можна змінити після цього;

Але var визначає звичайну змінну.

Значення константи не потрібно знати в час компіляції, але ви повинні призначити це значення рівно один раз.

Ви можете використовувати майже будь-який символ, який вам подобається, для постійних і змінних імен, включаючи символи Unicode;

напр

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

Як і Люк-Олівер, NullData та деякі інші, які тут говорили, letвизначає незмінні дані, а varвизначає змінні дані. Будь-яке, funcщо може бути викликане змінною, яка позначена, mutatingможе бути викликана лише в тому випадку, якщо вона є varзмінною (компілятор видасть помилку). Це також стосується funcs, які беруть inoutзмінну.

Однак, letа varтакож означає, що змінна не може бути переназначена. Він має два значення, обидва з дуже подібними цілями


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. Але спробуйте змінити масив та змінний рядок. Ви можете змінити їх значення, додавши або додаючи значення. Правильно, нехай об'єкти не можуть бути змінені за вказівником, їх адреса вказівника завжди буде однаковою, тому ви отримуєте помилку реініціалізації. Таким чином, ви можете сказати, нехай робить const покажчик, який не може бути змінений у майбутньому.
TheTiger

У Swift немає консолі.log. Перевірте тег OP
Dan Beaulieu

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

Let - це незмінна змінна, що означає, що її неможливо змінити, інші мови називають це постійною. У C ++ це можна визначити як const.

Var - змінна змінна, що означає, що її можна змінити. У C ++ (оновлення версії 2011 р.) Це те саме, що використовувати авто, хоча швидкий спосіб забезпечує більшу гнучкість у використанні. Це більш відомий змінний тип для початківців.


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 !

Let and Var не працює, використовуючи (Let and 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

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

На це майже всі відповіли, але ось ви можете запам’ятати, що до чого

Нехай завжди буде говорити те ж саме "нехай", як нехай це працює раз і завжди, так як для змінної "var" завжди можна змінити, отже їх називають змінними


-1

varце єдиний спосіб створити змінні у швидкому режимі. varне означає динамічну змінну, як у випадку з інтерпретованими мовами, такими як JavaScript. Наприклад,

var name = "Bob"

У цьому випадку для типу змінної nameробиться висновок, що ім'я типу String, ми також можемо створювати змінні, чітко визначаючи тип, наприклад

var age:Int = 20

Тепер якщо ви призначите рядок за віком, тоді компілятор видає помилку.

letвикористовується для оголошення констант. Наприклад

let city = "Kathmandu"

Або ми також можемо зробити,

let city:String = "Kathmandu"

Якщо ви спробуєте змінити значення міста, воно дає помилку під час компіляції.


-1

let використовується для констант, які неможливо змінити, а var - звичайна змінна

Приклад:

нехай name = "Bob" Щось на зразок name = "Jim" призведе до помилки, оскільки константа не може бути змінена.


-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" із "нехай ключове слово" і призначив значення "4". Коли я друкую “b”, я отримав 4 як вихід. Тоді я намагаюся призначити 5 "хай b", тобто я намагаюся змінити змінну "let", і я отримую помилку часу компіляції "Неможливо призначити значення:" b "є" нехай "константа".


-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 ++.

Я вважаю, що це механізм для підтримання свого роду коректності .


-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


-4

Знайшов хорошу відповідь, сподіваюся, що це може допомогти :) введіть тут опис зображення


4
Це насправді неправильно. letне означає, що об’єкт незмінний, це означає, що вказівник є незмінним. Щоб отримати еквівалентну функціональність в Obj-C, вам потрібно використовувати NSObject *const myObject = someobject;- Властивості такого об'єкта можуть бути змінені, але вказівник myObjectне може бути змінений, щоб вказувати на інший об'єкт.
SaltyNuts

1
Зовсім неправильна відповідь. Чи пробували ви з масивом let: NSMutableArray = NSMutableArray () ?? Ви можете додавати та вилучати об’єкти в / з цього. нехай робить те, const pointerщо не може бути змінено в майбутньому, але його значення може бути. Ви не можете реініціалізувати його, але можете використовувати його як хочете.
TheTiger
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.