在 Swift 中创建实例时是不是使用 var 或 let?

Posted

技术标签:

【中文标题】在 Swift 中创建实例时是不是使用 var 或 let?【英文标题】:Whether to use var or let during instances creation in Swift?在 Swift 中创建实例时是否使用 var 或 let? 【发布时间】:2017-08-05 16:57:11 【问题描述】:

在 Swift 中应该使用什么来创建类的实例,为什么?

请解释在 Swift 中创建实例时 let 和 var 的用法

下面是代码:-

class ConstantTest
    let constant: String
    init(constant: String) 
        self.constant = constant
    
    func printConstant() 
        print(constant)
    


let constanttest = ConstantTest(constant: "Hello")
constanttest.printConstant()

var test = ConstantTest(constant: "Hie")
test.printConstant()

【问题讨论】:

【参考方案1】:

使用每种方法的原因各不相同。解释这一点的最简单方法是let 用于定义常量,而var 用于定义变量。使用let 时,无法更改该值。因此,在您的应用程序中,如果您需要一个可以更改的值,请使用var。你也可以考虑搜索你的答案,因为这个问题有很多重复。

来源:https://developer.apple.com/library/content/documentation/Swift/Conceptual/Swift_Programming_Language/TheBasics.html

【讨论】:

实际上我不明白在使用 var 或 let 创建实例时我们会得到什么不同。我知道 var 和 let 类属性等功能。 根据我对 Swift 的最低理解,在这种情况下使用 let 是正确的,因为类型的实例永远不会改变。例如,如果您需要用新实例替换该实例,则不适合使用let。所以如果你需要这样做,那就是varconstanttest = ConstantTest(constant: "new test") 我尝试将 let 实例分配给一个新的 var 实例,即使在将类属性更改为 var 后我能够修改值,也没有出现错误。 @Rob(注意:- 我的疑问是关于实例应该使用 var 或 let 常量创建)var testnew = constanttest testnew.constant = "hey" print(testnew.constant)【参考方案2】:

在以下情况下使用let

它是一个常量(或者对于像class 这样的引用类型,如果引用不能被另一个引用替换);和 您可以在初始化过程中进行设置。

但是如果你以后需要能够改变它,使用var,比如值不是常量的真变量(或者在引用类型的情况下,如果你需要用另一个实例替换它)。但是在初始化过程中没有设置值的变量和属性,你必须使用var。例如,lazy 存储属性使用var,因为它们的值在初始化过程完成时没有设置,而只有在您第一次引用它时才设置。另一个示例包括视图控制器对其出口的引用,这些出口仅在稍后创建视图层次结构时才连接。

不用说,计算属性也使用var

但是,如果你可以使用let,你应该这样做,因为如果你知道什么是常量,什么是变量,那么编写安全代码会更容易。在您的示例中,您将使用let

注意:对于引用类型,如class 类型,let 并不意味着对象本身一定是不可变的,只是不能用另一个实例替换它。如果您想控制它是否不可变,请考虑使用值类型(例如 struct)。


让我看看能否让最后的注释更清楚。考虑:

class Foo 
    var value: String
    init(value: String) 
        self.value = value
    

那么以下是允许的:

let obj = Foo(value: "a")
obj.value = "b"           // changing mutable property of reference type, Foo, is permitted

但以下不是:

let obj = Foo(value: "a")
obj = Foo(value: "b")     // replacing `obj` with a new instance of `Foo`, is not

如果您不想更改 value 属性,您可以将 value 定义为不可变(或至少不公开可变),例如:

class Foo 
    let value: String      // or `private(set) var value: String`
    init(value: String) 
        self.value = value
    

或者不要将Foo 定义为class(引用类型),而是将其定义为struct(值类型):

struct Foo 
    var value: String
    init(value: String) 
        self.value = value
    


let obj = Foo(value: "a")
obj.value = "b"            // this is not permitted, because Foo value-type, `obj`, was declared with `let`, making it immutable

请注意,最后一个示例,将 Foo 声明为值类型(struct)确实从根本上改变了它,例如

var obj1 = Foo(value: "a")
var obj2 = obj1            // this value is a copy of `obj1` not a reference to the same object that `obj1` pointed to
obj1.value = "b"
print("\(obj1.value)")     // will print "b"
print("\(obj2.value)")     // will print "a"

但是值类型虽然需要稍微不同的思维方式来使用它们,但对于轻松编写安全代码非常有用。请参阅 WWDC 2015 Building Better Apps with Value Types in Swift。

【讨论】:

谢谢@Rob,但我的疑问是,类实例应该用 var 或 let 常量创建,为什么? 规则是一样的。除非您必须使用var,否则请使用let。如果您使用let,则表明此引用不能被另一个引用替换。 (它显然没有说明对象是否可变......考虑使用值类型,即struct。) 我尝试将 let 实例分配给一个新的 var 实例,即使在将类属性更改为 var 后我能够修改值,也没有出现错误。 var testnew = constanttest testnew.constant = "hey" print(testnew.constant @abhinavjha - 是的,这是我的最后一点。请注意,您可以更改constant 不是因为testnew 被声明为var(这是一个红鲱鱼),而仅仅是因为在我的示例中定义obj 时是否使用let,如果@987654357 @ 被定义为可变的,当您实例化它时使用let 确实改变了对象本身仍然可变的事实。只有指向它的指针是不可变的。我在问题的末尾添加了一些代码 sn-ps 来说明这一点。如果您使用值类型(即struct),所有这些行为都会发生变化。

以上是关于在 Swift 中创建实例时是不是使用 var 或 let?的主要内容,如果未能解决你的问题,请参考以下文章

使用 UILocalizedIndexedCollat​​ion 在 Swift 4.2 中创建 tableView 部分索引时出现错误“无法识别的选择器发送到实例”

在 Swift 4 中创建类的非零属性数组

在 CoreData 中创建实例

如何使用 UIKit 在 Swift 5 中创建具有内在高度的 UITableView?

使用 var 关键字在 Javascript 中创建对象时遇到问题

如何在 Swift 中创建独特的形状或 UIView