2016-02-21 30 views
5

ho qualcosa di simile a questo:È possibile utilizzare metatype (.Type) come chiave nel dizionario?

class Lumber { } 
class Fruit { } 

enum Size { 
    case Small 
    case Medium 
    case Large 
} 

let lumberSize = [ 
    Size.Small: "2x4", 
    Size.Medium: "4x6", 
    Size.Large: "6x10" 
] 

let fruitSize = [ 
    Size.Small: "grape", 
    Size.Medium: "apple", 
    Size.Large: "watermelon" 
] 

let size:[AnyObject.Type:Dictionary] = [ 
    Lumber.Type: lumberSize, 
    Fruit.Type: fruitSize 
] 

Sulla mia definizione del dizionario size, ottengo questo errore in tempo reale da Xcode Editor:

Tipo 'AnyObject.Type' non è conforme al protocollo ' Hashable '

Si potrebbe pensare che questo accontenterebbe le cose. Se voglio usare X come chiave in un dizionario, e non è lavabile, quindi semplicemente non può essere usato. Ciò ha senso.

Tuttavia, due cose mi fanno dubitare del messaggio di errore.

In primo luogo, in questo momento i messaggi di errore di Xcode Editor in tempo reale sono terribili oltre le basi. Diverse volte al giorno devo ignorare le sue supposizioni su ciò che è sbagliato e giocherellare con la sintassi fino a quando non viene accettato.

In secondo luogo, penso di leggere le parole nella documentazione che confutano il messaggio di errore. Nel Swift 2.2 Language Reference, sotto Tipi, si legge:

La metatipo di una classe, tipo di struttura, o l'enumerazione è il nome di quel tipo seguita da .Type

E nel Swift Standard Library ReferenceRiferimento struttura ObjectIdentifier letture:

In Swift, solo le istanze di classe e i metatipi hanno identità univoche.

E quella sezione elenca anche Hashable come protocollo a cui è conforme.

Se sto leggendo bene, quindi tutti i tipi hanno unoObjectIdentifier utilizzato da Hashable. Ero (erroneamente?) Usando Comparable come esempio. Possiamo confrontare i tipi perché il loro ObjectIdentifier è conforme a Comparable? Poiché ObjectIdentifier è conforme anche a Hashable, dovrei essere in grado di usarlo in un dizionario.

Quindi, al momento, sospetto che ciò che intendo fare sia effettivamente possibile, ma che semplicemente non riesco a correggere la sintassi.

risposta

7

Hashable è un protocollo che implementa ObjectIdentifier. Ciò significa che ObjectIdentifier(Lumber.Type) è lavabile, non che sia lo standard Lumber.Type. Si potrebbe provare a cambiare il codice per utilizzare Object Identifier, come in:

class Lumber { } 
class Fruit { } 

enum Size { 
    case Small 
    case Medium 
    case Large 
} 

let lumberSize = [ 
    Size.Small: "2x4", 
    Size.Medium: "4x6", 
    Size.Large: "6x10" 
] 

let fruitSize = [ 
    Size.Small: "grape", 
    Size.Medium: "apple", 
    Size.Large: "watermelon" 
] 

let size:[ObjectIdentifier: [Size: String]] = [ 
    ObjectIdentifier(Lumber): lumberSize, 
    ObjectIdentifier(Fruit): fruitSize 
] 

Questo compila, ma non sono sicuro se soddisfa le vostre esigenze specifiche. Personalmente, vorrei semplicemente usare la versione stringa del nome della classe come chiave - String(Lumber). vale a dire:

let size:[String: [Size: String]] = [ 
    String(Lumber): lumberSize, 
    String(Fruit): fruitSize 
] 
+0

Speravo di evitare la conversione String se solo per una comprensione più profonda di Swift. +1 per l'aspetto educativo. Se non capisco cosa sto cercando entro il prossimo fine settimana, accetterò questa (o un'altra) risposta. Grazie. – Jeff