2016-05-15 1 views
2

я создал следующий классПочему я могу изменить/переназначить постоянное значение, конкретизированный из класса

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

Как @Wain has said - это связано с характером ссылочных типов. Экземпляр, являющийся константой let, означает, что вы не можете назначить ему новую ссылку, но ничего не говорит о фактической изменчивости самого экземпляра.

Если вы измените свой класс на структуру, вы увидите, как поведение отличается значением типов, как изменение свойства изменяет фактическую стоимость вашего Person - поэтому вы не можете сделать это, если это let постоянная. Однако я несколько сомневаюсь, что вы захотите создать свою структуру, поскольку два человека с тем же именем не должны считаться одним и тем же лицом.

Если вы хотите, чтобы ваши свойства были назначены при инициализации (а затем доступны только для чтения для времени жизни экземпляра), я бы рекомендовал сделать их let константами (вместо того, чтобы сделать их сеттеры приватными). Это гарантирует, что вы не сможете даже изменить свое значение из своего класса после его назначения.

Правило, как долго вы даете свойству значения перед super.init() вызова - вы можете сделать это let константы (в этом случае, вы просто должны назначить их в Инициализатором перед использованием self).

class Person { 
    let firstName: String 
    let lastName: String 

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

... 
+0

Большое спасибо за помощь, очень хорошее объяснение! – SLN

+0

@SLN Happy to help :) – Hamish

2

Сам экземпляр класса является постоянным, так что вы не можете изменить его ссылаться на другой экземпляр, но экземпляр изменчиво, потому что его свойства создаются как var с.

Изменение firstName иметь частный сеттер и посмотреть, что вы можете сделать:

private(set) var firstName: String 
+0

Я начал понимать, я создал еще один класс, говоря «Животные», и я пытаюсь назначить его «john», после чего компилятор произвел ошибку. – SLN

1

Когда вы используете постоянный экземпляр класса в 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 

Ваше мышление не было неправильно, но немного путают причину вы бы совершенно правильно, если это была структура, а не класс.

+0

@ ded.exe большое спасибо за помощь, очень красивые примеры кода. – SLN

+0

Добро пожаловать, @SLN –