如果在Swift中使用"let"关键字定义常量/不可变量,那么"static"关键字有什么用途?

80

我有点困惑在Swift中使用static关键字。我们知道Swift引入了let关键字来声明不可变对象,比如声明一个表格视图单元格的id,在其生命周期内大多数情况下不会更改。那么像一些结构体声明中使用static关键字的用途是什么呢?

struct classConstants
{
    static let test = "test"
    static var totalCount = 0
}

let 关键字则具有相同的作用。在 Objective C 中,我们使用 static 来声明一些常量,例如:

static NSString *cellIdentifier=@"cellId";

除此之外,让我更加好奇的是在letvar关键字之前使用static关键字。有人能解释一下在哪里使用这个static关键字吗?更重要的是,在Swift中我们真的需要static吗?


8
如果你不知道什么是静态变量,我建议在开始使用 Swift 编写代码之前阅读一些面向对象编程的书籍。静态变量在一个对象的所有实例之间共享,如果它是 const (let),那么它就是不可变的。 - Daniel Krom
4
据我理解,在C、Objective C中,我使用static来声明一些常量。除此之外,我没有更多的了解。因此,我认为let和static是相同的。 - Poles
12
在C和Objective-C中,静态变量(除非你将它们定义为常量)并不是常量。你可能没有完全理解这一点,但没关系,人无完人,静态变量有点类似于全局变量。 - Daniel Krom
静态定义类型属性:“类型属性 实例属性是属于特定类型实例的属性。每次创建该类型的新实例时,它都有自己的一组属性值,与任何其他实例分开。您还可以定义属于类型本身而不是该类型的任何一个实例的属性。无论您创建多少个该类型的实例,这些属性只会有一个副本。这些属性称为类型属性。” “Swift编程语言(Swift 3)”。 - abanet
1
这是一个很好的问题。当实例属性的值在编译时完全已知(例如 let = "hello, world")时,就会出现一个合理的问题:为什么要使用静态属性而不是实例属性?人们会认为编译器足够聪明,可以优化掉重复的值。而且静态属性会带来一些轻微的不便(在使用属性之前必须包含类型命名空间)。 - Womble
7个回答

160
我会为你解释一下:
- `var`:用于创建一个变量 - `let`:用于创建一个常量 - `static`:用于创建一个具有`let`或`var`的type properties。这些属性在类的所有对象之间共享。
现在你可以组合起来得到所需的结果:
- `static let key = "API_KEY"`:常量类型属性 - `static var cnt = 0`:变量类型属性 - `let id = 0`:常量(只能赋值一次,但可以在运行时赋值) - `var price = 0`:变量
所以总结一下,var和let定义了可变性,而static和lack of define scope则定义了作用域。你可以使用static var来跟踪你创建了多少个实例,而你可能想要使用只有var的价格来区分不同的对象。希望这能帮助你理清一些事情。
示例代码:
class MyClass{
    static let typeProperty = "API_KEY"
    static var instancesOfMyClass = 0
    var price = 9.99
    let id = 5

}

let obj = MyClass()
obj.price // 9.99
obj.id // 5

MyClass.typeProperty // "API_KEY"
MyClass.instancesOfMyClass // 0

“let”:用于创建常量。使用“let”关键字声明的变量可以稍后(即在构造函数中)分配(仅一次),这与常量的定义相矛盾。如果我们将其与其他语言(如C#)进行比较,则“let”与C#中的“readonly”相同(而不是“const”)。 - MD TAREQ HASSAN
在Objective-C中,与static let相当的是什么,因为我必须在视图控制器中定义UIAplicationDidEnterBackground - iOS Developer
3
虽然我认为你的技术上是正确的,但你没有举例说明我何时需要使用静态变量而不是let变量。 - ICW
更明确地说,静态变量在类的每个实例中具有相同的值,而变量在每个类中都是唯一的变量。 - T.J.

130

静态变量在类的所有实例之间共享。将此示例放入playground中:

class Vehicle {
    var car = "Lexus"
    static var suv = "Jeep"
}

// changing nonstatic variable
Vehicle().car // Lexus
Vehicle().car = "Mercedes"
Vehicle().car // Lexus

// changing static variable
Vehicle.suv // Jeep
Vehicle.suv = "Hummer"
Vehicle.suv // Hummer
当您更改静态属性的变量时,该属性现在会在所有未来实例中更改。

Vehicle().car,返回 Lexus,但是当执行 let vehObj = Vehicle(); vehObj.car 时,返回 Mercedes。我不知道原因,这有什么区别吗?能帮我指导一下吗? - McDonal_11
vehObj.car 给了我 Lexus,我不知道为什么你得到了 Mercedes。 - Bobby
让suv = Vehicle(); suv.suv //Jeep; 让suv2 = Vehicle(); suv2.suv = "Hummer"; 让suv3 = Vehicle(); suv3.suv // Hummer; 如果我输入"suv.suv",它会返回"Jeep"还是"Hummer"? 值是否会更改所有该对象的实例,还是只有未来的实例? 如果它只更改未来的实例,为什么会这样? 为什么不是所有实例都更改? 如果这是一个愚蠢的问题,对不起。我想我没有看到过静态变量的应用。 - Mikael Weiss

13

静态变量属于类型而不是类的实例。您可以使用类型的完整名称来访问静态变量。

代码:

class IOS {

  var iosStoredTypeProperty = "iOS Developer"

  static var swiftStoredTypeProperty = "Swift Developer"

 }

 //Access the iosStoredTypeProperty by way of creating instance of IOS Class

let iOSObj = IOS()

print(iOSObj.iosStoredTypeProperty)  // iOS Developer


 //print(iOSObj.swiftStoredTypeProperty) 
 //Xcode shows the error 
 //"static member 'swiftStoredTypeProperty' cannot be used on instance of type IOS”


 //You can access the static property by using full name of the type
print(IOS.swiftStoredTypeProperty)  // Swift Developer

希望这能对你有所帮助。


1
"let"关键字定义常量,对于来自C#背景(比如我)的初学者来说有些困惑。在C#中,“let”可以看作是“只读变量”。(回答Swift中“let”关键字的工作原理是什么?)。使用staticlet同时定义常量。
public static let pi = 3.1416            // swift

public const double pi = 3.1416;         // C#
public static final double pi = 3.1416   // Java     

每当我使用 let 定义常量时,感觉像是在使用 C# 的 readonly。所以,我在 Swift 中同时使用 staticlet 来定义常量。

1
请看苹果文档中这个自我解释的例子,以了解类型属性和/或方法与类属性和/或方法之间的区别。
class SomeClass {
    static var storedTypeProperty = "Some value."
    static var computedTypeProperty: Int {
        return 27
    }
    class var overrideableComputedTypeProperty: Int {
        return 107
    }
}

静态属性只能在类型中声明,而不能全局声明。换句话说,在Swift中,静态属性等同于类型属性。要声明类型属性,必须使用static关键字。


1
你正在使用 "static" 来解释 "static",但提问者似乎并不真正了解其含义... - mfaani
3
@asma22 ?? 关键字“static”在Swift和C语言中有完全不同的含义。在Swift中,“static”表示“类型”(属性或函数)。 “static”和“class”属性或函数之间的区别在于,“class”属性或函数可以被覆盖,而“static”则不能被覆盖。由于大多数有编程背景的人会在其他上下文中使用“static”,因此苹果公司开始使用“type”一词进行解释,尽管关键字仍然是“static”。 - user3441734

1
让我为需要Objective-C参考的人解释一下。
希望大家记得,我们在Objective-C项目中使用一个常量文件来保存所有静态API密钥,如下所示。
/ In your *.m file
static NSString * const kNSStringConst = @"const value";

在这里,“Static”关键字并不意味着“kNSStringConst”是一个常量,它只是定义了“kNSStringConst”可以全局访问。而“const”关键字则使其成为常量。
现在让我们转到Swift。
在Swift中,“Static let”和“Static var”被视为“Type Properties”,这意味着它们可以通过它们的类型进行访问。
例如:
class World {
   static let largestPopulation = "China"
   static var secondLargestPopulation = "India"
}

World.largestPopulation = "German"   // Cannot assign to property: 'largestPopulation' is a 'let' constant
World.secondLargestPopulation = "UK"
World.secondLargestPopulation // UK

在这个例子中,有两个属性带有static关键字,一个是常量,另一个是变量。
  1. 如您所见,声明的常量Static let可以通过其类型访问,但无法更改。
  2. 声明的Static var不仅可以通过其类型访问,还可以被修改。因此,所有未来的实例都会被更改。

0

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接