Swift: создание массива со значением по умолчанию для отдельных экземпляров объекта

Я заметил немного странное ( и опасное поведение IMHO ) в создании массива со значением по умолчанию . Как указано в Swift 2.1: Типы сбора

Тип массива Swift также предоставляет инициализатор для создания массива определенного размера со всеми его значениями, установленными на одинаковое значение по умолчанию. Вы передаете этому инициализатору количество элементов, которые будут добавлены в новый массив (называемый count), и значение по умолчанию соответствующего типа (называемое repeatValue):

Точка: то же значение по умолчанию ; чтобы понять, как это работает, я попытался создать массив элементов этого classа example

class User { private struct Shared { static var sequence: Int = 0 } var id: Int var thinkTime: NSTimeInterval // typealias di Double init (thinkTime: NSTimeInterval) { User.Shared.sequence = User.Shared.sequence+1 id = User.Shared.sequence self.thinkTime = thinkTime } } 

и этот тестовый код:

 let howManyUsers: Int = 3 var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0)) let u2: User = User(thinkTime: 10) let u3: User = User(thinkTime: 10) users.append(u2) users.append(u3) users[1].thinkTime = 20 users[3].thinkTime = 30 for u in users { print("User id:\(u.id) thinktime:\(u.thinkTime)") } 

дает:

 User id:1 thinktime:20.0 User id:1 thinktime:20.0 User id:1 thinktime:20.0 User id:2 thinktime:30.0 User id:3 thinktime:10.0 

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

Каким образом, как можно более кратким и умным, получить массив отдельных экземпляров объектов , установленный с одинаковым значением по умолчанию (не тот же экземпляр, но несколько экземпляров, инициализированных с тем же значением по умолчанию)?

    Классы являются ссылочными типами, поэтому, как вы заметили, все элементы массива в

     var users = [User](count: howManyUsers, repeatedValue:User(thinkTime: 10.0)) 

    ссылается на тот же экземпляр объекта (который создается первым, а затем передается как аргумент инициализатору массива).

    Для типа struct вы получите другой результат.

    Возможное решение:

     var users = (0 ..< howManyUsers).map { _ in User(thinkTime: 10.0) } 

    Здесь для каждого из индексов массива создается экземпляр User .

    Если вам это нужно часто, вы можете определить метод init массива, который принимает параметр «автозакрытия»:

     extension Array { public init(count: Int, @autoclosure elementCreator: () -> Element) { self = (0 ..< count).map { _ in elementCreator() } } } var users = Array(count: howManyUsers, elementCreator: User(thinkTime: 10.0) ) 

    Теперь второй аргумент User(thinkTime: 10.0) компилятором в закрытие, а закрытие выполняется для каждого индекса массива.


    Обновление для Swift 3:

     extension Array { public init(count: Int, elementCreator: @autoclosure () -> Element) { self = (0 ..< count).map { _ in elementCreator() } } } 
    Interesting Posts

    Чтение писем из Gmail в C #

    Установка значения свойства Singleton в Firebase Listener

    Индикатор отключения питания мигает во время гибридного сна Vista?

    Получите div, чтобы принять 100% рост, минус фиксированная высота и нижний колонтитул

    рисовать диагональные линии в фоновом режиме с помощью CSS

    Динамически заменить содержимое метода C #?

    Как избежать зарезервированного слова в Oracle?

    Excel VBA «Отменить выбор»

    Сколько устройств можно подключить к USB-концентратору и как распределена мощность между ними?

    Любые советы о том, что делать, когда вы получаете загадочный синий экран в окнах?

    Есть ли конвертер printf для печати в двоичном формате?

    События .NET для запуска исполняемого файла процесса

    Как написать собственный конвертер для

    Скрыть открытые ярлыки на рабочем столе без административных привилегий

    Как сопоставить строку с строковыми литералами в Rust?

    Давайте будем гением компьютера.