2016-07-27 2 views
0

Dans le code ci-dessous:modèle Swift correspond à

protocol Serializable { 
} 

struct Owner: Serializable { 
    var name: String 
} 

struct Car: Serializable { 
    var owners: [Serializable] 
} 

let car = Car(owners: [Owner(name: "John"), Owner(name: "Mike")]) 

Mirror(reflecting: car).children.forEach { 
    switch $0.value { 
    case let value as Array<Serializable>: 
     print("Recognized!") 
    default: break 
    } 
} 

si

struct Car: Serializable { 
    var owners: [Serializable] 
} 

(propriétaires var est défini comme [Serializable])

case let value as Array<Serializable>: reconnaîtront, mais en cas:

struct Car: Serializable { 
    var owners: [Owner] 
} 

(propriétaires var est défini comme [Owner])

case let value as Array<Serializable>: ne le reconnaissent pas, même si Owner est conforme à Serializable protocole? Quelqu'un peut-il expliquer pourquoi?

J'ai essayé:

extension Array where Element: Serializable { 
    var representation: AnyObject { 
     return self.map { element in return "String" } 
    } 
} 

let arr: [Owner] = [Owner(name: "John"), Owner(name: "Mike")] 
arr.representation 

œuvres, si Swift reconnaît que [Owner] est [Serializable], pourquoi case let value as Array<Serializable> match de [Serializable] mais pas [Owner]?

+0

Avez-vous essayé 'cas Apprécions où la valeur est un tableau '? –

+0

Cela ne fonctionne pas. Fonctionne de la même manière que 'case let value comme Array ' –

+1

Quelqu'un a supprimé une réponse. Il a mentionné que ceci ne compilera pas: let arr: [Propriétaire] = [Propriétaire (nom: "John"), Propriétaire (nom: "Mike")]; let arr2 = arr comme? Array ... Erreur: Serializable n'est pas un sous-type de Owner. –

Répondre

0

Dans Swift, les protocoles ont une représentation de mémoire différente et distincte de celle des types concrets. Donc, la réponse courte est le tableau de Serializable est différent dans la mémoire d'un tableau d'un type qui est conforme à Serializable, et Swift n'a pas actuellement un mécanisme de casting entre les deux.

Plus de détails spécifiques, la débrouille dans ce discours WWDC:

https://developer.apple.com/videos/play/wwdc2016/416/

+0

Merci Daniel, va vérifier la vidéo –

0

Array<T> et T sont différents types, donc vous ne pouvez pas vous attendre à ce que sa conformité à un protocole ait un impact sur l'autre.

En ce qui concerne votre exemple:

extension Array where Element: Serializable { 
    var representation: AnyObject { 
     return self.map { element in return "String" } 
    } 
} 

Ici, vous vérifiez la conformité de chaque élément (Element), pas le tableau comme son propre type. Element est un type distinct de Array<Element>.

Il est difficile de savoir ce que vous devriez faire ici sans information supplémentaire, mais j'espère avoir répondu pourquoi vous n'obtenez pas les résultats que vous attendez.

+0

Vous avez raison sur 'extension Array où Element: Serializable' ... Array et T sont des types différents ..., mais ce qui est étrange pour moi, c'est que Swift reconnaît que [Owner] est [Serializable] puisque Owner implémente Serializable mais Je ne peux pas utiliser [Propriétaire] dans l'instruction de cas. –

+1

'Array ' et 'Array ' ne sont pas identiques. La seule raison pour laquelle l'extension fonctionne est parce que le type de l'élément - et non le générique lui-même - est testé pour la conformité.'Owner' est' Serializable', mais c'est tout. –