Swiftの `let`と` var`の違いは何ですか?


321

AppleのSwift言語letとの違いは何varですか?

私の理解では、それはコンパイルされた言語ですが、コンパイル時に型をチェックしません。それは私を混乱させます。コンパイラーは型エラーをどのようにして知るのですか?コンパイラがタイプをチェックしない場合、それは本番環境の問題ではないですか?


35
letは定数、varは変数です。
Collin Henderson

2
@Edwardコンパイル時に型チェックを行わないとはどういう意味ですか?私の知る限り、それは静的に型付けされていますが、コンパイラーがそれ自体で理解できる場合、型は推論されます。しかし、私は25ページだけです... ;-)
Joachim Isaksson

4
これはトピックに関するものですが、不適切なフレーズの質問です。少なくとも2つの質問があります(i)letvarの違い。(ii)タイプセーフとタイプ推論。さらに、ポスターが制作段階について言及したとき、彼は実行時に本当に意味しました。
Kevin Le-Khnle 2014年

1
さらに、コレクション(配列と辞書)を定義する変数で使用されるvarは、変更可能なコレクションを作成します(参照だけでなく、コレクションの内容も変更できます。varの他の使用方法は、関数に渡されるパラメーターを変更することです:func foo(var bar:Int)を使用すると、関数スコープでローカルにパラメーターバーを変更できます
Laurent

回答:


407

letキーワードは定数を定義します。

let theAnswer = 42

theAnswer後で変更することはできません。これが、を使用して何もweak記述できない理由ですlet。これらは実行時に変更する必要があり、var代わりに使用する必要があります。

var通常の変数を定義します。

何が面白い:

定数の値はコンパイル時既知である必要はありませんが、値を1回だけ割り当てる必要があります。

別の奇妙な機能:

Unicode文字を含む、定数名と変数名には、ほぼすべての文字を使用できます。

let 🐶🐮 = "dogcow"

抜粋:Apple Inc.「The Swift Programming Language」iBooks。https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewBook?id=881256329

編集

コメントは他の事実を回答に追加することを求めているため、これをコミュニティWiki回答に変換します。答えを自由に編集して、より良いものにしてください。


1
CおよびC ++では、UCNを介してUnicode識別子も使用できます。コンパイラがUnicodeソースエンコーディングをサポートしている場合は、Unicode文字を直接使用できます。たとえばauto 🐶🐮 = "dogcow";、clangのC ++で動作します。
bames53 2014年

131
@ bames53大丈夫、私は次のようなプログラムをデバッグしたいのか確信が持てませんif 😍 === 💝 { 💔 = ♠︎ }
::

REPLに適用されますか?REPLで定数を再割り当てできるからです。
アーメドアルハフード2014年

1
まず、上記のように、これはREPLではまったく異なります。第二に、それが定数である場合、それは1ではありません。これはコンパイラでうまく機能します:let foo = [1,2,3]; foo [2] = 5; println( "(foo)")// [
Kevin Frost

31
この回答は、最も賛成されていますが、値型ではなくオブジェクトを参照するときのlet / varの動作についての言及がありません。重要なのは、どちらの場合でも、オブジェクトのプロパティを変更することはできますが、別のオブジェクトを参照するようにポインタを変更することができないことです。これは、整数と文字列を含む基本的な例からすぐにはわかりません。
SaltyNuts 2015

33

Swiftプログラミング言語の本によると

Cと同様に、Swiftは変数を使用して、識別名で値を格納および参照します。Swiftは、値を変更できない変数を広範囲に使用します。これらは定数と呼ばれ、Cの定数よりもはるかに強力です。

varletはどちらも参照であるためletconst参照です。基本型を使用して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参照です。「const ref」という概念はありません。一度バインドされると、参照は常に同じメモリアドレスにバインドされ、変更したり、「シード解除」することはできません。varは「ポインター」、letは「constポインター」であることを意味していると思います
AyBayBay

@AyBayBayあなたが書いていることは例えばC ++で正しいですが、上記のスニペットは証明すると思いますが、Swiftではそうではありません。ポインターを使用すると、ポインターの計算と直接のメモリアクセスが可能になりますが、ここでも同様です。-編集:すべての参照が実際にconst参照であるという証拠は、すべてのプログラミング言語に当てはまりません。
Krzak

ウィキペディアのポインタによると、BTW は参照です
Krzak

2
私はあなたの専門用語が間違っていることに同意します。 バインドされている識別子が参照先かどうかvarletは関係ありません。タイプがタイプの場合、struct概念的には値です。タイプがaの場合、classそれは概念的には参照であり、let使用される場合、参照は定数です。CTest構造体の場合、letTest割り当ては機能しません。
JeremyP 2015年

1
タイプがstruct値タイプの場合、概念はありません。class参照タイプと同じです。値型を変更する場合、この型の新しいインスタンスを作成します。developer.apple.com/swift/blog/?id=10したがって、letバインドされた値タイプのフィールド/プロパティを変更することはできません。
Krzak

15

let定数のvar定義と変数の定義に使用されます。


7

唯一の「定数/変数」の通常の概念よりも大きいオブジェクト空間での値とインスタンスの変更可能性の正しいパラダイムである、可変性/非可変性の概念によってこの違いを述べる方が良いかもしれません。さらに、これはObjective Cのアプローチに近いものです。

2つのデータ型:値型と参照型。

値タイプのコンテキストでは:

'let'は定数値を定義します(変更不可)。'var'は、変更可能な値(可変)を定義します。

let aInt = 1   //< aInt is not changeable

var aInt = 1   //< aInt can be changed

参照タイプのコンテキストでは:

データのラベルは値ではなく、値への参照です。

if aPerson = Person(name:Foo、first: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
2014

4
不変性?それは不可能です!確かに反勧め。あなたが探している言葉は「不変性」かもしれないと思います:-)
paxdiablo 14

6

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

コンパイル時にすべての変数(または)のタイプを定義する必要あります。変数を設定しようとするコードは、そのタイプ(またはサブタイプ)のみを使用できます。実行時にを割り当てることができますが、そのはコンパイル時にわかっている必要があります。letvar


4

let- constant
var-variable

[定数vs変数]
[構造体vsクラス]

公式ドキュメントdocs.swift.orgは言う

値は、constant一方で、それのセット一度に変更することはできませんvariable将来的に異なる値に設定することができます。

この用語は実際には再割り当てメカニズムを説明しています

可変性-変更可能-オブジェクトの状態は作成後に変更できます

値と参照タイプ[概要]

値(構造体、列挙型)

Swift structはそれらの可変性ステータスを変更できます:

let+ struct= immutable= 値の定数は、
それができないことが再割り当てまたは変更します

var+ struct= mutable
それは可能な再割り当てまたは変更します

参照タイプ(クラス)

スウィフトclassesmutable優先事項です

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と、このパラメータが有効varstructなり、状態を変更でき、これらの変更は関数スコープの外に表示されます

//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を使用して文字列を定義すると、変数に割り当てることで特定の文字列を変更(または変更)でき(その場合、文字列を変更できます)、 letを使用して文字列を定義すると、定数(その場合は変更できません)変更):

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は通常の変数を定義します。

定数の値はコンパイル時に既知である必要はありませんが、値を1回だけ割り当てる必要があります。

ユニコード文字を含め、定数および変数名には、ほぼすべての文字を使用できます。

例えば

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変数を受け取るにも適用されます。

しかし、letvarも変数が再割り当てできないことを意味します。2つの意味があり、どちらも目的が非常に似ています


0

var値は、初期化後に変更できます。しかし一度値をつければ価値は変わらない。

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のような非オブジェクト値で問題ありません。しかし、可変配列と可変文字列を試してください。値を追加または追加することで、それらの値を変更できます。正しいのはオブジェクトをそのポインターで変更できないようにすることです。そのポインターアドレスは常に同じになるため、再初期化エラーが発生します。あなたが言うことができるので、letが将来的に変更することはできませんのconstポインタになります。
TheTiger

Swiftにはconsole.logはありません。OPのタグをチェックする
Dan Beaulieu 2016年

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バージョンの更新)では、autoを使用する場合と同じですが、swiftを使用することでより柔軟に使用できます。これは、初心者にはよく知られている変数型です。


0

letは定数値なので、変更することはできません。

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

Varは変数であり、変更できます(ただし、別のデータ型に定義されていない場合)。

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

変数を別のdataTypeに変更しようとしても、機能しません

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

1
してみましょうする必要がありましょう
TheTiger 2015

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とVarが小文字で(letとvar)を使用して機能していない。
Abhishek 2015年

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は変更できない定数です

例えば

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

0

letとvarにはすでに多くの違いがありますが、主な違いの1つは次のとおりです。

let is compiled fast in comparison to var.

-1

誰もがほとんどこれに答えましたが、これはあなたが何が何であるかを思い出すことができる方法です

「let」については、これが1度だけ機能するのと同じ考え方で、常に「var」変数は常に変更できるため、変数の名前と呼ばれます。


-1

var変数を迅速に作成する唯一の方法です。varJavaScriptのようなインタプリタ言語の場合のように、動的変数を意味しません。例えば、

var name = "Bob"

この場合、変数の型はnamenameがtypeであると推定Stringされます。たとえば、型を明示的に定義して変数を作成することもできます。

var age:Int = 20

文字列をageに割り当てると、コンパイラーがエラーを出します。

let定数を宣言するために使用されます。例えば

let city = "Kathmandu"

または、私たちも行うことができます、

let city:String = "Kathmandu"

市の値を変更しようとすると、コンパイル時にエラーが発生します。


-1

letは、varが通常の変数であるときに変更できない定数に使用されます

例:

let 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"

上記の例を理解してみましょう。「var keyword」を使用して新しい変数「a」を作成し、値「1」を割​​り当てました。「a」を出力すると、1として出力されます。次に、「var a」に2を割り当てます。つまり、変数「a」の値を変更しています。varとして宣言したので、コンパイラエラーが発生することなく実行できます。

2番目のシナリオでは、「letキーワード」を使用して新しい変数「b」を作成し、値「4」を割り当てました。「b」を出力すると、出力として4が得られました。次に、「let b」に5を割り当てようとします。つまり、「let」変数を変更しようとしていますが、「値に割り当てられません:「b」は「let」定数です」というコンパイル時エラーが発生します。


-3

現在でもマニュアルを読んでいますが、これはC / C ++ constポインターに非常に近いと思います。言い換えれば、違いのようなものchar const*char*。コンパイラーは、参照の再割り当て(ポインター)だけでなく、コンテンツの更新も拒否します。

たとえば、この構造体があるとします。これはクラスではなく構造体であることに注意してください。私の知る限り、クラスには不変の状態の概念はありません。

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 ++ポインターで期待したとおりです。

これは一種のconst-correctnessをサポートするメカニズムだと思います。


-3

letキーワードで定数を宣言し、varキーワードで変数を宣言します。

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

複数の定数または複数の変数を、コンマで区切って1行で宣言します。

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 2015

1
全く間違った答え。let配列で試しましたか:NSMutableArray = NSMutableArray() ?? これに対してオブジェクトを追加および削除できます。聞かせて作るconst pointer、将来の変化にすることはできませんが、その値をすることができます。再初期化することはできませんが、必要に応じて使用できます。
TheTiger
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.