2015-12-26 12 views
5

Stavo attraversando this link.Differenza tra l'estensione di una classe conforme a un protocollo VS l'estensione di un protocollo basato su condizioni simili?

Ma io davvero non ottenere la differenza tra la logica di sotto dei due frammenti di codice:

1. Estendere SOLO quei UIViewControllers conformi alla ErrorPopoverRenderer protocollo.

protocol ErrorPopoverRenderer { 
    func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool) 
} 

extension UIViewController: ErrorPopoverRenderer { //Make all the UIViewControllers that conform to ErrorPopoverRenderer have a default implementation of presentError 
    func presentError(message: String, withArrow shouldShowArrow: Bool, backgroundColor: UIColor, withSize size: CGSize, canDismissByTappingAnywhere canDismiss: Bool) 
{} 
} 

2. Estendere il protocollo solo per quei UIViewControllers conformi ad esso.

extension ErrorPopoverRenderer where Self: UIViewController { 
func presentError() { 
} 
} 

O modi, Qualsiasi UIViewController sottoclasse che conforme al protocollo avrà attuazione metodo predefinito ma in estensione UIViewController OR protocollo di estensione. Qual è la differenza logica? favore correggetemi se sbaglio

risposta

1

Prima di tutto, si crea un protocollo ErrorPopoverRenderer con un progetto per il metodo presentError(...). Successivamente, estendere la classe UIViewController per conformarsi a questo protocollo, implementando il modello (obbligatorio) per il metodo presentError(...).

Ciò significa che è possibile creare una sottoclasse di UIViewController) con il vincolo di protocollo aggiuntivo ErrorPopoverRenderer per la sottoclasse. Se UIViewController non era stato esteso per conformarsi al protocollo ErrorPopoverRenderer, il codice successivo nell'esempio si è collegato sarebbe tra maiuscole e compilazione errore di tempo (... does not comply to protocol ErrorPopoverRenderer)

class KrakenViewController: UIViewController, ErrorPopoverRenderer { 
    func failedToEatHuman() { 
     //… 
     //Throw error because the Kraken sucks at eating Humans today. 
     presentError(ErrorOptions(message: "Oh noes! I didn't get to eat the Human!", size: CGSize(width: 1000.0, height: 200.0))) //Woohoo! We can provide whatever parameters we want, or no parameters at all! 
    } 
} 

Tuttavia, v'è un possibile problema con questo metodo, come presentato nel vostro link:

Ora dobbiamo implementare ogni parametro ogni volta che vogliamo presentare un ErrorView a . Questo tipo di problemi è dovuto al fatto che non è possibile fornire valori predefiniti di alle dichiarazioni di funzione del protocollo.

Così del protocollo ErrorPopoverRenderer non è destinato esclusivamente all'uso da UIViewController: s (o sottoclassi stesse), quindi la soluzione di cui sopra non è molto generiche.

Se vogliamo avere un più ampio utilizzo di ErrorPopoverRenderer, abbiamo posto le specifici modelli per ogni tipo di classe che potrebbe fare uso del protocollo in estensioni del protocollo. Questo è davvero accurato in quanto le parti più specifiche dei modelli per il metodo presentError() possono essere specificate in modo diverso per classi diverse che possono eventualmente essere conformi al protocollo e il metodo presentError() può essere reso più minimalista.

cito, dall'esempio:

Utilizzando Auto qui indica che tale estensione sarà sempre e solo prendere luogo se e solo se il conformer eredita da UIViewController. Questo ci dà l'abilità di assumere che ErrorPopoverRenderer è in effetti un UIViewController senza nemmeno estendere UIViewController.

In questo metodo, dal momento che il codice ora sa (abbiamo fatto, già nel 1.) che si tratta di un controller della vista che chiamerà presentError(), possiamo collocare la specifica UIViewController roba direttamente nella realizzazione progetto, e non è necessario inviarlo come una lunga lista di argomenti.

Quindi, 2. è, per questo uso specifico, una sorta di approccio più "generico", nel senso che abbiamo un po 'ridurre al minimo la duplicazione del codice (chiamando presentError() vs presentError(... lots of args ...) da diversi diversi UIViewController: s).

3

La differenza è che il primo:

extension UIViewController: ErrorPopoverRenderer { } 

effettivamente estendeUIViewController classe, così ogni istanza di UIViewController ora ha accesso a metodi & oggetti di protocollo. Ciò non significa che estenderà la classe che implementa il protocollo, significa che in questo momento stai implementando il protocollo per questa classe. Di solito è necessario implementare alcuni dei metodi & proprietà in tale estensione.

Dove nel secondo:

extension ErrorPopoverRenderer where Self: UIViewController {} 

effettivamente aggiungere metodi & proprietà per UIViewController che implementa il protocollo ErrorPopoverRenderer.

In sostanza nel primo si estende la classe con l'attuazione intero protocollo, e nel secondo si estende classe, ma solo se questa classe o sottoclasse implementa il protocollo ErrorPopoverRenderer.

Problemi correlati