2015-12-26 8 views
5

Ben this link.Bir protokole uygun bir sınıfi uzatmak arasındaki fark VS benzer bir duruma dayanan bir protokolü genişletiyor mu?

geçmekte olduğu Ama gerçekten iki kod snippet'ine aşağıda arasında mantıksal bir fark dont almak:

1. protokolü ErrorPopoverRenderer uygun SADECE bu UIViewControllers genişletme. buna uygun SADECE bu UIViewControllers için protokolünü genişletme

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..

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

Ya yollar, protokole uygun olacaktır Herhangi UIViewController alt sınıf varsayılan yöntem uygulanması ancak UIViewController'ın uzantısı VEYA protokol uzantısı olacaktır. Mantıksal fark nedir? Ben her

cevap

1

İlk hatam varsa sen yönteme presentError(...) için planı ile protokol ErrorPopoverRenderer oluşturmak, lütfen beni düzeltin. Daha sonra, presentError(...) yöntemine ilişkin (zorunlu) planı uygulayarak bu protokole uymak için UIViewController sınıfını genişletmeniz gerekir.

Bu, alt sınıf için UIViewController) alt sınıfına ErrorPopoverRenderer ek protokol kısıtlaması alt sınıfını uygulayabileceğiniz anlamına gelir. UIViewController protokole ErrorPopoverRenderer uygun şekilde genişletildi olmasaydı, bağlantılı örnekte müteakip kod sunulduğu gibi (... does not comply to protocol ErrorPopoverRenderer)

Ancak
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! 
    } 
} 

, bu yöntemle olası bir sorun vardır derleme zamanı hatası harf olur senin link:

Artık her parametreyi biz bir ErrorView sunmak istiyorum her zaman uygulamak zorunda. Bu tür bir hata, protokol işlevi bildirimlerine varsayılan değerlerini sağlayamadığımızdan dolayı berbat.

protokol ErrorPopoverRenderer Yani sadece UIViewController tarafından kullanım için uygun değildir: s (ya da bunların alt sınıfları), daha sonra yukarıdaki solüsyonu çok genel değildir.

biz ErrorPopoverRenderer daha geniş kullanıma sahip olmak istiyorsanız

, biz protokol uzantıları protokol faydalanmak olabilir her sınıf türü için spesifik planları yerleştirin. Bu yöntem, presentError() metodunun ErrorPopoverRenderer planlarının daha spesifik kısımlarının, protokole uygun olabilecek farklı sınıflar için farklı şekilde belirtilebildiği ve bu nedenle presentError() yönteminin daha minimalist hale getirilebileceği gibi, gerçekten temizdir.

ben örnekten, alıntı:

burada Self kullanarak o uzatma sadece hiç konformerde UIViewController devralır ancak ve ancak gerçekleşeceğini gösterir. Bu, bize , ErrorPopoverRenderer'ın UIViewController'ı bile genişletmeden ve UIViewController olduğunu kabul etmemizi sağlar. kod artık presentError() arayacak bir görünüm denetleyicisi olduğunu (biz zaten 1. yılında, yaptığımız) bilir beri bu yöntemde

, biz, doğrudan planı uygulanmasında belirli UIViewController şeyler yerleştirebilirsiniz ve uzun bir argüman listesi olarak göndermeye gerek yok.

Dolayısıyla, 2., biz biraz kod tekrarını en aza anlamda bu özel kullanım, daha "genel" yaklaşımının bir tür için (: s birkaç farklı UIViewController den presentError() vs presentError(... lots of args ...) arayarak gibi). böylece UIViewController her örneği artık sahip protokolden yöntemlere & özelliklerine erişmek,

extension UIViewController: ErrorPopoverRenderer { } 

aslında UIViewController sınıfını genişleten:

3

fark ilk olmasıdır. Bu, protokolü uygulayan sınıfı genişleteceği anlamına gelmez, şu anda bu sınıf protokolünü uygulayacağınız anlamına gelir. Genellikle bu uzantıdaki & yöntemlerinden bazılarını uygulamanız gerekir. İkinci birinde

:

extension ErrorPopoverRenderer where Self: UIViewController {} 

aslında protokolü ErrorPopoverRenderer uygulayan UIViewController için yöntemler & özelliklerini ekleyin.

ilk Eğer bütün protokol uygulaması ile sınıfını genişletir ve ikinci birinde sınıfı genişletip Temelde içinde

fakat sadece bu sınıf veya alt sınıf protokolü ErrorPopoverRenderer uygulaması halinde.

İlgili konular