在Swift中,let和var有什么区别?

在苹果的Swift语言中,letvar有什么区别?

在我的理解中,它是一种编译语言,但它不在编译时检查类型。这让我很困惑。编译器如何知道类型错误?如果编译器不检查类型,这不是生产环境的问题吗?

当我试图将值赋给let时,会给出这个错误:

不能分配给属性:'variableName'是一个'let'常量
将'let'改为'var'使其可变

206711 次浏览

let关键字定义了一个常量:

let theAnswer = 42

之后不能更改theAnswer。这就是为什么weak不能用let写任何东西的原因。它们在运行时需要改变,你必须使用var来代替。

var定义了一个普通变量。

有趣的是:

常量不需要在编译时知道的值,但必须只赋值一次。

另一个奇怪的特征是:

你几乎可以用任何你喜欢的字符作为常数和变量 名称,包括Unicode字符:

let 🐶🐮 = "dogcow"

摘自:苹果公司《快速编程语言》。“iBooks。https://itunes.apple.com/WebObjects/MZStore.woa/wa/viewBook?id=881256329


社区维基

因为注释要求在答案中添加其他事实,因此将此转换为社区wiki解答。请随意编辑答案,使其更好。

let用于定义常量,var用于定义变量。

和C语言一样,Swift使用变量来存储和引用一个标识名称的值。Swift还大量使用了值不可更改的变量。这些常量被称为常量,比c中的常量强大得多。当你处理不需要更改的值时,整个Swift都使用常量,使代码更安全,意图更清晰。

https://docs.swift.org/swift-book/LanguageGuide/TheBasics.html

let定义了一个常量。它的值设置一次且仅一次,但不一定在声明时设置。例如,你可以使用let在类中定义一个必须在初始化时设置的属性:

class Person {


let firstName: String
let lastName: String


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

在这种设置下,在调用(例如)Person(first:"Malcolm", last:"Reynolds")创建Person实例后赋值给firstNamelastName是无效的。

必须在编译时为所有变量(letvar)定义了一个类型,并且任何试图设置变量的代码只能使用该类型(或子类型)。你可以在运行时赋值价值,但它的类型必须在编译时已知。

虽然目前我还在阅读手册,但我认为这非常接近C/ c++ const指针。换句话说,类似于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标记一个mutator方法。因为aaa1这个名字是常量,所以你不能对它调用任何mutator方法。这正是我们在C/ c++指针上所期望的。

我相信这是一种支持某种< em > < / em > const-correctness东西的机制。

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

let用于声明一个常量值-在给出初始值后将不会更改它 var用于声明一个变量值-你可以随心所欲地改变它的值

用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

也许用可变性/不可变性的概念来陈述这种差异更好,这是对象空间中值和实例可变性的正确范式,它大于唯一的“常量/变量”。通常的观念。 此外,这更接近Objective C方法

2 .数据类型:值类型和引用类型。

在值类型的上下文中:

'let'定义一个常量(不可变)。'var'定义了一个可变值(mutable)。

let aInt = 1   //< aInt is not changeable


var aInt = 1   //< aInt can be changed

在参考类型中:

数据的标签不是值,而是对值的引用。

if Person = Person(名称:Foo,第一个:Bar)

person不包含此人的数据,但包含此人数据的引用。

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.

例如:

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)

而且

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


let aPersonA = aPersonB // won't compile

let aPersonA = Person(name:A, first: a)


aPersonA.name = "B" // will compile

Swift编程语言文档中的声明常量和变量部分指定了以下内容:

使用let关键字声明常量,使用var关键字声明变量。

确保理解Reference类型是如何工作的。与值类型不同,尽管引用类型的实例被声明为常量,但对象的底层属性可以改变。请参阅文档的类是引用类型部分,并查看他们更改frameRate属性的示例。

我在其他语言中遇到的常量的另一个区别是:不能为以后的初始化常量(let)应该在声明常量时初始化。

例如:

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

变量

var variableValue : Int // No issues

"使用let作为常量,使用var作为变量"

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

根据Swift编程语言书

和C语言一样,Swift使用变量存储和请参考存储值 识别的名字。Swift还大量使用了变量whose 数值不可修改。这些被称为常数,而且很多

varlet都是参考文献,因此let常量引用。 使用基本类型并不能真正显示letconst的不同之处。 区别在于当它与类实例(引用类型)一起使用时:

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"

< em >让< / em >用于定义常量,< em > var < / em >用于定义变量。 你使用< em > var < / em >定义字符串,那么特定的字符串可以通过赋值给一个变量(在这种情况下它可以被修改)来修改(或突变),如果你使用< em >让< / em >定义字符串,它是一个常量(在这种情况下它不能被修改):

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

是一个常量,所以它永远不能被改变。

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.

Let关键字定义一个常量

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,那么……

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

主要的区别是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 !

找到了一个很好的答案,希望能有所帮助:)enter image description here

就像Luc-Oliver、NullData和其他一些人在这里说过的,let定义不可变数据,而var定义可变数据。可以在标记为mutating的变量上调用的任何func只能在var变量上调用(编译器将抛出错误)。这也适用于包含inout变量的func

然而,letvar也意味着变量不能被重新赋值。它有两个意思,目的都很相似

非常简单:

  • let是常量。
  • var是动态的。

描述一下:

let创建一个常量。(有点像NSString)。一旦你设置了它,你就不能改变它的值。你仍然可以把它添加到其他东西,并创建新的变量。

var创建一个变量。(有点像NSMutableString),所以你可以改变它的值。但这个问题已经被回答了好几次。

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();

每个人都回答了这个问题,但有一种方法可以让你记住什么是什么

“让”总是说同样的想法“让”让这个工作一次和永远至于“var”变量总是可以改变,因此它们被称为变量

关键字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

Let是一个不可变变量,意思是它不能被改变,其他语言称它为常量。在c++中,你可以把它定义为const。

Var是一个可变变量,这意味着它可以被改变。在c++(2011版本更新)中,它与使用auto相同,尽管swift允许更大的灵活性。这是初学者更熟悉的变量类型。

var是在swift中创建变量的唯一方法。var并不像javascript这样的解释性语言那样意味着动态变量。例如,

var name = "Bob"

在这种情况下,变量name的类型被推断为name的类型为String,我们也可以通过显式定义type来创建变量

var age:Int = 20

现在如果你将一个字符串赋值给age,编译器就会给出错误。

let用于声明常量。例如

let city = "Kathmandu"

或者我们也可以,

let city:String = "Kathmandu"

如果您试图更改city的值,则会在编译时给出错误。

Let用于不能修改的常量,而var是普通变量

例子:

let name = " Bob " 像name = " Jim "这样的东西会抛出一个错误,因为一个常量不能被修改

var是一个变量,你可以在任何时间任意修改它

例如

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

是常量,不能被改变

例如

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

尽管你已经得到了let和var之间的许多区别,但一个主要的区别是:

let is compiled fast in comparison to var.

简单的区别

Let =(不能更改)

Var =(随时更新)

来源: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。然后我给“var a”赋值2,即我正在修改变量“a”的值。这样做不会引起编译器错误,因为我声明为var。

在第二个场景中,我用“let关键字”创建了一个新变量“b”,并赋值为“4”。当我输出b时,我得到4作为输出。然后我尝试将5分配给“let b”,即我试图修改“let”变量,我得到编译时错误“不能分配给值:' b '是一个' let '常量”。

Swift let和var

let - constant
var - variable

< p > [常量vs变量]
[结构vs类] < / p >

官方文件docs.swift.org

constant的值一旦设置就不能更改,而variable可以在将来设置为不同的值。

这个术语实际上描述了一个重新分配机制

可变性

可变性-可变-对象的状态可以在创建__abc0后改变

值和引用类型__abc0

引用类型(类)

Swift的classesmutable a-priory

var + class
它可以是重新分配改变了

let + class = 地址常数
可以是重新分配,也可以是改变了

值(结构、枚举)

Swift的struct可以改变它们的可变性状态:

var + struct = mutable
它可以是重新分配改变了

< p > let + struct = * immutable或者说unmodifiable<一口>[对]< /一口> <一口>[例]< /一口> <一口>[例]< /一口> = 数值常数
可以是重新分配改变了

*immutable - check testStructMutability test

实验:

class MyClass {
var varClass: NSMutableString
var varStruct: String
    

let letClass: NSMutableString
let letStruct: String
    

init(_ c: NSMutableString, _ s: String) {
varClass = c
varStruct = s
        

letClass = c
letStruct = s
}
}


struct MyStruct {
var varClass: NSMutableString
var varStruct: String
    

let letClass: NSMutableString
let letStruct: String
    

init(_ c: NSMutableString, _ s: String) {
varClass = c
varStruct = s
        

letClass = c
letStruct = s
}
    

    

//mutating function block
func function() {
//            varClass = "SECONDARY propertyClass" //Cannot assign to property: 'self' is immutable
//            varStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'self' is immutable
}


mutating func mutatingFunction() {
varClass = "SECONDARY propertyClass"
varStruct = "SECONDARY propertyStruct"
}
}

可能的用例

func functionVarLetClassStruct() {
    

var varMyClass = MyClass("propertyClass", "propertyStruct")
    

varMyClass.varClass = "SECONDARY propertyClass"
varMyClass.varStruct = "SECONDARY propertyStruct"
    

//        varMyClass.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
//        varMyClass.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
    

let letMyClass = MyClass("propertyClass", "propertyStruct")
    

letMyClass.varClass = "SECONDARY propertyClass"
letMyClass.varStruct = "SECONDARY propertyStruct"
    

//        letMyClass.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
//        letMyClass.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
    

var varMyStruct = MyStruct("propertyClass", "propertyStruct")
    

varMyStruct.varClass = "SECONDARY propertyClass"
varMyStruct.varStruct = "SECONDARY propertyStruct"
    

//        varMyStruct.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
//        varMyStruct.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
    

let letMyStruct = MyStruct("propertyClass", "propertyStruct")
    

//        letMyStruct.varClass = "SECONDARY propertyClass" //Cannot assign to property: 'letMyStruct' is a 'let' constant
//        letMyStruct.varStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letMyStruct' is a 'let' constant
    

//        letMyStruct.letClass = "SECONDARY propertyClass" //Cannot assign to property: 'letClass' is a 'let' constant
//        letMyStruct.letStruct = "SECONDARY propertyStruct" //Cannot assign to property: 'letStruct' is a 'let' constant
    

}

mutating -改变Struct的函数

可以将结构体的方法标记为mutating

  1. 指示此函数更改内部属性值
  2. 你只能在var变量上调用变异函数
  3. 当突变函数完成时,结果可见
func testStructMutatingFunc() {
//given
var varMyStruct = MyStruct("propertyClass", "propertyStruct")
    

//when
varMyStruct.mutatingFunction()
    

//than
XCTAssert(varMyStruct.varClass == "SECONDARY propertyClass" && varMyStruct.varStruct == "SECONDARY propertyStruct")
    

// It is not possible to call a mutating function on a let variable
let letMyStruct = MyStruct("propertyClass", "propertyStruct")
//        letMyStruct.mutatingFunction() //Cannot use mutating member on immutable value: 'letMyStruct' is a 'let' constant
}

inout在函数内

  1. inout允许你重新分配/修改一个传递的(原始)值。
  2. 只能在inout参数内传递var变量
  3. 当功能完成时,结果可见

inout有一个next流:

  1. 传递的值在函数调用之前被复制到被复制的值中
  2. 复制的值在函数完成后被赋值为传递的值
//InOut
func functionWithInOutParameter(a: inout MyClass, s: inout MyStruct) {
    

a = MyClass("SECONDARY propertyClass", "SECONDARY propertyStruct") //<-- assign
s = MyStruct("SECONDARY propertyClass", "SECONDARY propertyStruct") //<-- assign
}




func testInOutParameter() {


//given
var varMyClass = MyClass("PRIMARY propertyClass", "PRIMARY propertyStruct")
var varMyStruct = MyStruct("PRIMARY propertyClass", "PRIMARY propertyStruct")


//when
functionWithInOutParameter(a: &varMyClass, s: &varMyStruct)


//then
XCTAssert(varMyClass.varClass == "SECONDARY propertyClass" && varMyClass.varStruct == "SECONDARY propertyStruct")
XCTAssert(varMyStruct.varClass == "SECONDARY propertyClass" && varMyStruct.varStruct == "SECONDARY propertyStruct")
    

    

// It is not possible to pass let into inout parameter
let letMyClass = MyClass("PRIMARY propertyClass", "PRIMARY propertyStruct")
let letMyStruct = MyStruct("PRIMARY propertyClass", "PRIMARY propertyStruct")
//        functionWithInOutParameter(a: &letMyClass, s: &letMyStruct) //Cannot pass immutable value as inout argument: 'letMyClass', 'letMyStruct' are 'let' constants
}

*你偷窃能够突变let + struct

func testStructMutability()  {
//given
let str: NSMutableString = "propertyClass"
let letMyStruct = MyStruct(str, "propertyStruct")
    

//when
str.append(" SECONDARY")
    

//then
XCTAssert(letMyStruct.letClass == "propertyClass SECONDARY")
}

尽可能使用let。必要时使用var

[结构突变] .

let关键字用于声明一个常量,var关键字用于声明一个变量。用这些引用、指针或值创建的变量。

它们之间的区别是,当你使用let创建一个变量时,它将在声明后成为常量,以后不能修改或重新赋值。相反,具有var的变量可以立即赋值,也可以稍后赋值,或者根本不赋值。在swift中,您必须非常明确地声明您所声明的内容。

在swift语言中let是一个常量,意思是is不能重赋,但var可以重赋

let question = "what is the difference between let and var?"


question = "another question" // this line cause syntax error

var answer = "let is constant and var is simple variable"


answer = "let can't be reassigned var can be reassigned" // this line will be excecuted