2015-11-16 6 views
0

Я создал класс городов, который состоит из нескольких объектов города, каждый из которых имеет конкретные данные. Поскольку данные фиксированы, я хочу назначить его в функции init() объекта Cities.Заполнить массив объектами

// CASE 1 - ERROR 

class Cities : NSObject { 
    var cityList:[City] 
    override init() { 
     cityList = [] 
     let city = City() 

     city.fill("LA" , "USA") 
     self.cityList.append(city) 
     city.fill("Amsterdam" ,"Netherlands") 
     self.cityList.append(city) 
     city.fill("Beijing" , "China") 
     self.cityList.append(city) 

Результат: Пекин Пекин


// CASE 2 - CORRECT 

class Cities : NSObject { 
    var cityList:[City] 
    override init() { 
     cityList = [] 
     var city:City 

     city = City(name: "LA" ,country: "USA") 
     self.cityList.append(city) 
     city = City(name: "Amsterdam", country: "Netherlands") 
     self.cityList.append(city) 
     city = City(name: "Beijing" , country: "China") 
     self.cityList.append(city) 

Результат: LA, Амстердам, Пекин

Когда я запускаю этот первый сценарий, я получаю хороший объект городов и массив имеет 3 города в нем, весь Пекин.

В правильном случае данные назначаются функцией init объекта City. Теперь все работает так, как ожидалось.

В обоих случаях я создал только один объект Город: город. Почему это различие в поведении Свифт? Использование Apple Swift version 2.1

+0

Рассмотрите, можете ли вы использовать структуру для этого вместо класса, можете ли вы использовать семантику значения вместо ссылки? – Wain

ответ

1

В случае 1 вы создали только один объект City, это линия, которая создает объект:

let city = City() 

Город - это класс, который является ссылочным типом. Это означает, что он указывает вам то же место в памяти. Ваш первый вызов:

city.fill("LA" , "USA") 

установить свойства «LA» и «США», второй вызов

city.fill("Amsterdam" ,"Netherlands") 

пойти на то же место в памяти и переопределить свойства с новыми значениями и то же самое происходит с третьим вызовом, который является последним вызовом, поэтому вы получаете значения. Вашего массива cityList имеет три элемента, который указует на то же место в памяти, поэтому вы видите один и тот же объект:

cityList[0] === cityList[1] === cityList[2] 

В случае 2 каждый раз, когда вы создаете новый объект вызова конструктора, например:

City(name: "LA" ,country: "USA") 

Constructor выделить новый адрес памяти, который заканчивается с совершенно новым объектом, поэтому каждый раз, когда вы звоните:

City(name:...) 

ваш объект city указывает на другое место в памяти.

+0

Это звучит логично. Для правильного случая. Поэтому, вызывая конструктор, я всегда создаю новый объект. Это также означает, что объект City (LA) удаляется, когда я создаю Амстердам. Или он остается в памяти, но не может быть использован? – Vincent

+0

Да, когда вы вызываете конструктор, вы создаете новый объект, и в вашем примере город будет хранить новую ссылку, которая указывает на ваш новый объект, а старая ссылка будет переопределяться. В вашем примере вы добавляете его в массив, чтобы счетчик ссылок увеличивался, и вы все равно можете получить к нему доступ, вызвав, например, cityList [0]. Bu, если вы не добавите его в массив, объект будет освобожден. – Greg

+0

Отличное объяснение. благодаря – Vincent

1

В первом случае вы создаете отдельный объект City, а затем заполняете его разными данными, но это один объект, который вы создали его один раз, и просто поместили в него три указателя, когда вы звоните fill изменить данные внутри этого единого объекта и в конце вашего init у вас есть массив с 3 указателями на один объект, который содержит последние данные

во втором случае вы создаете 3-х различных объектов и добавить его в массив

Смежные вопросы