【问题标题】:Why I can change/reassigned a constant value that Instantiated from a class为什么我可以更改/重新分配从类实例化的常量值
【发布时间】:2016-05-15 13:09:14
【问题描述】:

我创建了以下类

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

【问题讨论】:

    标签: swift class constants


    【解决方案1】:

    正如@Wain has said——这是由于引用类型的性质。实例是 let 常量仅意味着您不能为其分配新的引用 - 但没有说明实例本身的实际可变性。

    如果您将类更改为结构,您将看到 value 类型的行为有何不同,因为更改属性会更改 Person 的实际值 - 因此您无法如果它是 let 常量,请这样做。但是我有点怀疑您是否希望将 Person 设为结构,因为不应将两个同名的人视为同一个人。

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

    规则是,只要您在调用 super.init() 之前给属性一个值 - 您可以将其设为 let 常量(在这种情况下,您只需在使用 self 之前在初始化程序中分配它们) .

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

    【讨论】:

    • @SLN 乐于助人:)
    【解决方案2】:

    类实例本身是一个常量,所以你不能改变它来引用另一个实例,但是实例是可变的,因为它的属性被创建为vars。

    firstName 更改为私人二传手,看看你能做什么:

    private(set) var firstName: String
    

    【讨论】:

    • 我开始明白了,我创建了另一个类Animals,并尝试将其分配给john,然后编译器触发了一个错误。
    【解决方案3】:

    当您在 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
    

    但是你可以在类中创建一个常量并在初始化中设置这个值

    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
    

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

    【讨论】:

    • @ded.exe 非常感谢您的帮助,非常好的代码示例。
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2011-05-13
    • 2017-03-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-01
    相关资源
    最近更新 更多