Si je crée une structure Swift sans init
, alors je peux appeler l'initialiseur membre par défaut généré par le compilateur, comme ceci:
struct OrderFill {
let price:Int
let qty: Int
let timeStamp: NSDate
}
let o = OrderFill(price: 2, qty: 1, timeStamp: someDate)
Ce que j'aimerais faire, c'est créer une méthode d'init pratique pour désérialiser à partir d'un dictionnaire, qui enchaîne ensuite l'init par défaut par membre. Quelque chose comme
struct OrderFill {
let price:Int
let qty: Int
let timeStamp: NSDate
init(dict:[String:AnyObject]) throws {
self.init(
price: dict["price"] as! Int
qty: dict["qty"] as! Int
timeStamp: try parseDate(dict["ts"] as! String)
}
}
let o = OrderFill(someDict)
Quand j'essaie d'écrire ce code, le compilateur (Xcode 7.2) me donne l'erreur "Argument supplémentaire 'qty' dans l'appel" comme s'il ne voyait pas le membre par défaut et essayait d'appeler récursivement init(dictionary)
Je peux écrire mon propre init membre par membre, ou je peux simplement assigner les propriétés directement à partir de ma init(dictionary)
, mais ce serait bien si je pouvais enchaîner l'appel. Y a-t-il un moyen de le faire rapidement?
Ajoutez votre propre initialiseur comme extension à votre structure. Les extensions ne peuvent pas supprimer les fonctionnalités existantes, elles conserveront donc l'initialiseur par défaut de struct.
struct OrderFill {
let price: Int
let qty: Int
let timeStamp: NSDate
}
extension OrderFill {
init(dict: [String: AnyObject]) throws {
self.init(
price: dict["price"] as! Int,
qty: dict["qty"] as! Int,
timeStamp: try parseDate(dict["ts"] as! String)
)
}
}
let o = OrderFill(someDict)
De les documents Apple sur l'initialisation :
Les types de structure reçoivent automatiquement un initialiseur membre par membre s'ils ne définissent aucun de leurs propres initialiseurs personnalisés
et
Notez que si vous définissez un initialiseur personnalisé pour un type de valeur, vous n'aurez plus accès à l'initialiseur par défaut (ou à l'initialiseur membre, s'il s'agit d'une structure) pour ce type. Cette contrainte empêche une situation dans laquelle une configuration essentielle supplémentaire fournie dans un initialiseur plus complexe est contournée par quelqu'un qui utilise accidentellement l'un des initialiseurs automatiques à la place.
Par conséquent, la réponse est [~ # ~] non [~ # ~] . Vous ne pouvez pas fournir un initialiseur personnalisé et utiliser l'initialiseur membre par membre en même temps.
Cela ressemble à this Swift evolution proposition parle d'étendre les capacités de l'initialiseur membre actuel. Mais bien sûr, cela n'est pas encore sorti, vous pouvez cependant toujours jeter un œil pour en savoir un peu plus sur les limites de la situation actuelle.