我在指南中读到了这个简单的解释:
在编译时不需要知道常量的值,但是必须为它赋值一次。
但我想要比这更详细一些。如果常量引用了一个对象,我还可以修改它的属性吗?如果它引用了一个集合,我可以添加或删除它中的元素吗?我来自C#背景;它与readonly
的工作方式类似(除了能够在方法体中使用它),如果不能,它有什么不同?
答案 0 :(得分:44)
let
有点像C中的const
指针。如果引用带有let
的对象,则可以更改对象的属性或调用方法它,但您不能为该标识符分配不同的对象。
let
也会对集合和非对象类型产生影响。如果您使用struct
引用let
,则无法更改其属性或调用其任何mutating func
方法。
对集合使用let
/ var
非常类似于可变/不可变的Foundation集合:如果将数组分配给let
,则无法更改其内容。如果您使用let
引用字典,则无法添加/删除键/值对或为键指定新值 - 它确实是不可变的。如果要分配到,附加或以其他方式改变数组或字典,则必须使用var
声明它。
(在Xcode 6 beta 3之前,Swift数组有一个奇怪的值和参考语义混合,并且在分配给let
时部分可变 - 现在已经消失了。)
答案 1 :(得分:4)
最好根据静态单一分配(SSA)来考虑let
- 每个SSA变量都分配给完全一次。在像lisp这样的函数式语言中,你(通常)不使用赋值运算符 - 名称只与一个值绑定一次。例如,下面的名称y
和z
只绑定一次值(每次调用):
func pow(x: Float, n : Int) -> Float {
if n == 0 {return 1}
if n == 1 {return x}
let y = pow(x, n/2)
let z = y*y
if n & 1 == 0 {
return z
}
return z*x
}
这有助于更正确的代码,因为它强制执行不变性并且没有副作用。
以下是命令式程序员如何计算5的前6个幂:
var powersOfFive = Int[]()
for n in [1, 2, 3, 4, 5, 6] {
var n2 = n*n
powersOfFive += n2*n2*n
}
显然n2
是一个循环不变量,所以我们可以使用let
代替:
var powersOfFive = Int[]()
for n in [1, 2, 3, 4, 5, 6] {
let n2 = n*n
powersOfFive += n2*n2*n
}
但真正有功能的程序员会避免所有的副作用和突变:
let powersOfFive = [1, 2, 3, 4, 5, 6].map(
{(num: Int) -> Int in
let num2 = num*num
return num2*num2*num})
答案 2 :(得分:3)
Swift使用两种基本技术来存储程序员使用名称访问的值: let 和 var 。如果您永远不会更改与该名称关联的值,请使用 let 。如果您希望该名称引用一组不断变化的值,请使用 var 。
let a = 5 // This is now a constant. "a" can never be changed.
var b = 2 // This is now a variable. Change "b" when you like.
常量引用的值永远不会改变,但是如果它是类的实例,则常量引用的值可以改变。
let a = 5
let b = someClass()
a = 6 // Nope.
b = someOtherClass() // Nope.
b.setCookies( newNumberOfCookies: 5 ) // Ok, sure.
将数组分配给常量时,无法再从该数组中添加或删除元素。但是,任何该数组元素的值仍可能会更改。
let a = [1, 2, 3]
a.append(4) // This is NOT OK. You may not add a new value.
a[0] = 0 // This is OK. You can change an existing value.
不能以任何方式更改分配给常量的字典。
let a = [1: "Awesome", 2: "Not Awesome"]
a[3] = "Bogus" // This is NOT OK. You may not add new key:value pairs.
a[1] = "Totally Awesome" // This is NOT OK. You may not change a value.
这是我对这个主题的理解。请在需要的地方纠正我。对不起,如果问题已经得到解答,我这样做的部分原因是为了帮助自己学习。
答案 3 :(得分:2)
首先," let关键字定义一个常量" 让来自C#background(就像我)的初学者感到困惑。在阅读了许多Stack Overflow答案后,我得出结论
实际上,在swift中没有常数的概念
常量是在编译时解析的表达式。对于C#和Java,必须在声明期间分配常量:
public const double pi = 3.1416; // C#
public static final double pi = 3.1416 // Java
Apple doc(定义常量使用" let"):
在编译时不需要知道常量的值,但是必须只为该值赋值一次。
在C#术语中,你可以想到"让"作为"readonly"
变量
斯威夫特"让" == C#" readonly"
答案 4 :(得分:0)
使用Swift的let关键字,F#用户会感到宾至如归。 :)
在C#术语中,如果允许该构造,则可以将“let”视为“readonly var”,即:只能在声明点绑定的标识符。
答案 5 :(得分:0)
Swift属性:
Swift Properties official documentation
最简单的形式是,存储属性是一个常量或变量,它存储为特定类或结构的实例的一部分。存储的属性可以是变量存储属性(由
var
关键字引入),也可以是常量存储属性(由let
关键字引入)。
示例:
下面的示例定义了一个名为FixedLengthRange的结构,该结构描述了一系列整数,其范围长度一旦创建就无法更改:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
FixedLengthRange
的实例具有名为firstValue
的变量存储属性和名为length
的常量存储属性。在上面的示例中,length
在创建新范围时初始化,之后无法更改,因为它是一个常量属性。