我在指南中读到了这个简单的解释:
常量的值不需要在编译时知道,但必须恰好分配一次值。
但我想要比这更详细的信息。如果常量引用了一个对象,我还能修改它的属性吗?如果它引用了一个集合,我能添加或删除其中的元素吗?我来自C#背景; 它是否类似于readonly
的工作方式(除了能在方法体中使用),如果不同,那么它有什么不同之处?
我在指南中读到了这个简单的解释:
常量的值不需要在编译时知道,但必须恰好分配一次值。
但我想要比这更详细的信息。如果常量引用了一个对象,我还能修改它的属性吗?如果它引用了一个集合,我能添加或删除其中的元素吗?我来自C#背景; 它是否类似于readonly
的工作方式(除了能在方法体中使用),如果不同,那么它有什么不同之处?
let
类似于C语言中的常量指针。如果您使用let
引用对象,可以更改对象的属性或调用其方法,但不能将不同的对象分配给该标识符。
let
还涉及集合和非对象类型。如果您使用let
引用一个struct
,则无法更改其属性或调用任何mutating func
方法。
使用let
/var
处理集合时,其工作方式类似于可变/不可变Foundation集合:如果将数组赋值给let
,则无法更改其内容。如果您使用let
引用字典,则无法添加/删除键/值对或为键分配新值-它是完全不可变的。如果您想要在数组或字典中分配下标、追加或以其他方式进行突变,则必须使用var
声明它。
(在Xcode 6 beta 3之前,Swift数组具有奇怪的值和引用语义混合,并且在分配给let
时部分可变 - 现在已经消失了。)
NSDictionary
/NSMutableDictionary
一致吗? - Jiaaro最好将let
的思想看作是静态单赋值(SSA)——每个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
}
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})
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.
a[0] = 0
,不允许进行可变操作,因此这是不被允许的。 - Vlad首先,对于那些来自C#背景(比如我)的初学者来说,“let”关键字定义常量的说法很容易造成困惑。通过阅读许多Stack Overflow答案,我得出了以下结论:
实际上,在Swift中并没有常量的概念。
常量是在编译时解析的表达式。对于C#和Java来说,常量必须在声明时被赋值:
public const double pi = 3.1416; // C#
public static final double pi = 3.1416 // Java
苹果文档(使用“let”定义常量):
常量的值在编译时无需知道,但必须准确赋值一次。
从C#的角度来看,“let”可以被视为“只读(readonly)”变量。
Swift中的“let”等同于C#中的“readonly”。
F#用户将会对Swift的let关键字感到非常熟悉。:)
从C#的角度来看,你可以把"let"看作是"readonly var",如果这个构造被允许的话,也就是说,一个只能在声明点绑定的标识符。
Swift 属性:
在其最简单的形式中,存储属性是作为特定类或结构体实例的一部分存储的常量或变量。存储属性可以是可变存储属性(由
var
关键字引入)或常量存储属性(由let
关键字引入)。
例如:
下面的示例定义了一个名为 FixedLengthRange 的结构体,该结构体描述了一个整数范围,其范围长度在创建后无法更改:
struct FixedLengthRange {
var firstValue: Int
let length: Int
}
FixedLengthRange
的实例有一个名为firstValue
的可变存储属性和一个名为length
的常量存储属性。在上面的示例中,length
在创建新范围时被初始化,因为它是一个常量属性,所以之后不能更改。