2015-05-11 5 views
32

Sia questa dichiarazioneQual è la differenza tra un protocollo esteso da AnyObject e un protocollo di solo classe?

protocol SomeProtocol : AnyObject { 
} 

e questa dichiarazione

protocol SomeProtocol : class { 
} 

sembrano fare in modo che solo le classi possono essere conformi a questo protocollo (vale a dire che le istanze del protocollo sono riferimenti agli oggetti), e non avere altri effetti

C'è qualche differenza tra loro? Si dovrebbe preferire l'altro? Se no, perché ci sono due modi per fare la stessa cosa?

Sto usando l'ultimo Xcode rilasciato 6.3.1.

risposta

1

Ho fatto un misspoke prima. @ Martinin dovrebbe davvero rispondere a questa domanda, poiché è lui a correggermi e a fornire le informazioni corrette.

La differenza reale è che un protocollo con il qualificatore di classe può essere applicato solo a una classe, non a una struct o enum.

Martin, perché non rispondi e l'OP può accettare la tua risposta?

+3

Ma sembra che un protocollo che eredita da AnyObject possa essere applicato anche a una classe, non a una struct o enum. 'protocollo SomeProtocol: AnyObject {}; struct Foo: SomeProtocol {} 'fornisce l'errore del compilatore' tipo non di classe 'Foo' non può essere conforme al protocollo di classe 'SomeProtocol''. (Ho la sensazione che in realtà non c'è differenza, ma non posso provarlo.) –

+0

Suppongo che abbia senso, dal momento che AnyObject è anche solo oggetti di classe. Dovresti usare il 'protocollo SomeProtocol: Any' se vuoi una struct o enum per conformarsi a quel protocollo. Mi chiedo quale sia il punto del qualificatore di classe. Ho (erroneamente) assunto che limitasse il protocollo alla classe, non alle istanze della classe, ma i documenti indicano chiaramente altrimenti. –

+0

_La vera differenza è che un protocollo con il qualificatore di classe può essere applicato solo a una classe, non a una struct o enum_? No, non è una differenza, esattamente lo stesso vale per 'AnyObject' dato che solo gli oggetti possono essere conformi a questo, né enumerare né le strutture possono essere usate dove è previsto' AnyObject'. La vera differenza è che 'AnyObject' può essere una classe Swift o un oggetto Obj-C (o qualcos'altro, che sarebbe conforme a tale protocollo), ma solo le classi Swift possono essere conformi a' class'. – Mecki

4

AnyObject è un protocollo a cui tutte le classi sono implicitamente conformi (source). Quindi direi che non c'è differenza: puoi usare entrambi per richiedere un vincolo di classe.

5

Aggiornamento: Dopo essersi consultato con the powers that be, le due definizioni sono supposto essere equivalente, con AnyObject essere utilizzato come uno stand-in, mentre class veniva finito. In futuro il secondo eliminerà il primo ma, per ora, presentano alcune piccole differenze.

La differenza sta nella semantica delle dichiarazioni @objc. Con AnyObject, l'aspettativa è che le classi conformi possano o meno essere oggetti Objective-C corretti, ma la lingua li tratta comunque (in quanto a volte si perde il dispatch statico). Da questo punto di vista è possibile trattare uno AnyObject e altri. vincolo protocollo come un modo per chiedere @objc funzioni membro come mostrato nell'esempio nella documentazione per AnyObject nel STL:

import Foundation 
class C { 
    @objc func getCValue() -> Int { return 42 } 
} 

// If x has a method @objc getValue()->Int, call it and 
// return the result. Otherwise, return nil. 
func getCValue1(x: AnyObject) -> Int? { 
    if let f:()->Int = x.getCValue { // <=== 
     return f() 
    } 
    return nil 
} 
// A more idiomatic implementation using "optional chaining" 
func getCValue2(x: AnyObject) -> Int? { 
    return x.getCValue?() // <=== 
} 
// An implementation that assumes the required method is present 
func getCValue3(x: AnyObject) -> Int { // <=== 
    return x.getCValue() // x.getCValue is implicitly unwrapped. // <=== 
} 

Lo stesso esempio cade immediatamente se si modifica che ad un protocollo class -deriving:

import Foundation 

protocol SomeClass : class {} 

class C : SomeClass { 
    @objc func getCValue() -> Int { return 42 } 
} 

// If x has a method @objc getValue()->Int, call it and 
// return the result. Otherwise, return nil. 
func getCValue1(x: SomeClass) -> Int? { 
    if let f:()->Int = x.getCValue { // <=== SomeClass has no member 'getCValue' 
     return f() 
    } 
    return nil 
} 

// A more idiomatic implementation using "optional chaining" 
func getCValue2(x: SomeClass) -> Int? { 
    return x.getCValue?() // <=== SomeClass has no member 'getCValue' 
} 

// An implementation that assumes the required method is present 
func getCValue3(x: SomeClass) -> Int { // <=== 
    return x.getCValue() // <=== SomeClass has no member 'getCValue' 
} 

così sembra class è una versione più conservativa di AnyObject che deve essere utilizzato quando vi interessa soltanto la semantica di riferimento e non sulle ricerche membri dinamici o Objective-C bridging.

+1

Prima di tutto, grazie per la tua risposta. (Forse non si dovrebbe usare "AnyClass" perché questo è già un alias di tipo per AnyObject.Type.) La differenza tra 'AnyObject' e, diciamo,' MyClassProtocol', definita come 'protocollo MyClassProtocol: class {}' è ora chiaro. Quello che mi manca ancora è la differenza tra 'protocol MyObjectProtocol: AnyObject {}' e 'protocol MyClassProtocol: class {}'. –

+2

Sto ancora lottando (e forse è colpa mia) per trovare un esempio concreto in cui "protocollo Protocol: AnyObject {}" non è intercambiabile con il protocollo Protocol: class {} '. –

+0

Quindi qual è la tua conclusione ora? Se capisco correttamente Joe Groff, non c'è * nessuna * differenza tra 'protocollo SomeProtocol: AnyObject {}' e 'protocol SomeProtocol: class {}' a tutti, ma tu stai sostenendo che * "... per ora, fanno presente alcune piccole differenze "*. Per favore perdona la mia ostinazione, ma non riesco ancora a vedere come il tuo codice dimostri questa differenza. –

0

Nella sezione The Swift Programming Language (Swift 4), nella sezione Protocolli di sola classe. Ha menzionato solo AnyObject, ma non class.

È possibile limitare l'adozione del protocollo ai tipi di classe (e non a strutture o enumerazioni) aggiungendo il protocollo AnyObject all'elenco di ereditarietà di un protocollo.

protocol SomeClassOnlyProtocol: AnyObject, SomeInheritedProtocol { 
    // class-only protocol definition goes here 
} 

Per questo motivo, io ti suggerirei di usare AnyObject sopra class per il nuovo codice o nuovo progetto. Oltre a questo, non vedo alcuna differenza evidente tra loro.