为什么我可以更改/重新分配从类实例化的常量值

时间:2016-05-15 13:09:14

标签: swift class constants

我创建了以下类

class Person {
    var firstName: String
    var lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }


    func fullName() -> String {
        return "\(firstName) \(lastName)"
    }
}

然后我从类

中实例化了一个常量值
 let john = Person(firstName: "Johnny", lastName: "Applessed")

问题:为什么我可以更改变量john的内容?这不是常数吗?有人能为我解释一下,非常感谢。

john.firstName = "John"

print(john.firstName) // -> John

3 个答案:

答案 0 :(得分:5)

作为@Wain has said - 这是由于引用类型的性质。实例为let常量仅表示您无法为其指定新引用 - 但对实例本身的实际可变性没有任何说明。

如果您将类更改为结构,您将看到行为与类型的不同,因为更改属性会更改Person的实际值 - 因此您如果它是let常数,则无法这样做。但是我有点怀疑你是否想让你的Person成为一个结构,因为两个同名的人不应该被认为是同一个人。

如果您只希望在初始化时分配属性(然后在实例的生命周期内只读),那么我建议将它们设为let常量(而不是将它们的setter设为私有)。这将确保您在分配后甚至无法从班级中更改其价值。

规则只要您在super.init()调用之前为属性赋值 - 您可以将其设为let常量(在这种情况下,您只需在使用前将其分配到初始化器中) self)。

class Person {
    let firstName: String
    let lastName: String

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }

...

答案 1 :(得分:3)

类实例本身是一个常量,因此您无法将其更改为引用另一个实例,但该实例是可变的,因为它的属性创建为firstName

private(set) var firstName: String 更改为拥有私人设定器并查看您可以执行的操作:

model

答案 2 :(得分:2)

当您在swift中使用类的常量实例时,并不意味着您无法更改类属性。它'意味着您无法在此常量

中实例化新对象
let person = Person(firstName: "Johnny", lastName: "Appleseed")
person = Person(firstName: "John", lastName: "Appleseed") //--->It gets error: Cannor assign to value: 'person' is a 'let' constant

但是你可以在内部类中创建一个常量并在init

中设置这个值
class Person {
    let firstName: String  
    let lastName: String 

    init(firstName: String, lastName: String) {
        self.firstName = firstName
        self.lastName = lastName
    }


    func fullName() -> String {
        return "\(firstName) \(lastName)"
    }
}

//Tip: Don't init the class constants in declaration time or will get the same above error. Just init this constants at constructor/initialization of class.

现在你得到了你想要的预期结果,即使创造了一个' var'该对象的实例

var person = Person(firstName: "Johnny", lastName: "Appleseed")
person.firstName = "John"  //--->It gets error: Cannor assign to value: 'person' is a 'let' constant

person = Person(firstName: "John", lastName: "Snow")
person.firstName = "Johnny"  //--->It gets error: Cannor assign to value: 'person' is a 'let' constant

你的想法并没有错,但有点混乱,因为如果它是一个结构而不是一个类,你就完全正确。