2015-10-03 9 views
8

bemerkte ich ein wenig seltsam (und gefährlich IMHO) behavoir in ein Array mit einem Standardwert erstellen. Wie in Swift 2.1: Collection Types angegebenSwift: ein Array mit einem Standardwert von verschiedenen Objektinstanzen Erstellen

Swift Array-Typ bietet auch einen Initialisierer für mit allen ihren Werten auf den gleichen Standardwert ein Array von einer bestimmten Größe zu schaffen. Sie geben diese initializer die Anzahl der Elemente in das neue Array (genannt count) und einen Standardwert des entsprechenden Typs (genannt Wiederholter) hinzugefügt werden:

Der Punkt ist: gleichen Standardwert; um zu verstehen, wie es funktioniert, habe ich versucht, eine Reihe von Elementen dieses Beispiels Klasse erstellen

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 
    } 
} 

und diesen Testcode:

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)") 
} 

gibt:

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 

die definitiv Beweisen Sie den Initialisierer mit der Anzahl der Elemente, die dem neuen Array hinzugefügt werden sollen, und einem Standardwert des entsprechenden Typs: dieselbe Objektinstanz

der den Weg ist, so präzise und intelligente wie möglich eine Reihe von unterschiedlichen Objektinstanzen zu erhalten, mit dem gleichen Standardwert instatiated (nicht die gleiche Instanz aber eine Reihe von Fällen mit dem gleichen Standardwert initialisiert) ?

Antwort

16

Klassen sind Referenztypen, also - alle Elemente in

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

Referenz die gleiche Objektinstanz (das zuerst erstellt wird und dann als Argument an das Array Initialisierer bestanden) - wie man bemerkt.

Für einen struct Typ würden Sie ein anderes Ergebnis erhalten.

Eine mögliche Lösung:

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

Hier wird ein User Instanz für jeden der Array-Indizes erstellt wird.

Wenn Sie, dass häufig dann könnte man einen Array init Methode definieren, die einen „autoclosure“ Parameter übernehmen:

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)) 

nun das zweite Argument User(thinkTime: 10.0) vom Compiler in einen Verschluss gewickelt ist, und die Der Abschluss wird für jeden Array-Index ausgeführt.


Update für Swift 3:

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