2014-09-18 14 views
14

Kodumun daha kolay okunabilmesi için çeşitli türlerde kapaklar için Swift'de yazı tipi takma adları kullanıyorum. Ben kapanışları aşağıdaki temel set var:Swift'de bir kapatma türü takma adını nasıl "generify" yaparım?

public typealias FailureClosure = (error: NSError?) -> Void 
public typealias ProgressClosure = (progress: Float32) -> Void 
public typealias BasicClosure =() -> Void 
Ben jenerik diziler destekleyen bir kapatma typealias eklemek istiyorum, ama bunun için sözdizimi anlamaya görünüyor olamaz

. Ancak bu kadar almak mümkün olduğu gibi, ama

public typealias ArrayClosure = <T>(array:[T]?) -> Void 

herkes bunun nasıl biliyor mu derleme zamanı hatası " 'T' bildirilmemiş Çeşidi Kullanımı" olsun? Ya da mümkün olsa bile?

+0

Tek bir ayrıntıda şunu belirtmek isterim ki 'typealias', 'T' tanımlandığı sınıflarda tanımlayabilirsiniz. Eğer 'T' nesnesinin genel bir türü ise, 'classealias' öğesini bu sınıfın içinde normal gibi oluşturabilir ve kullanabilirsiniz. Bunu yaparsanız bir not: sınıfın dışında 'typealias' tanımlanmadı, bu yüzden hala tam kapanış sözdizimini görecekler. – vrwim

cevap

10

Hayır, şu anda mümkün değil. o mümkün olsaydı, beklediğiniz sözdizimi olacaktır:

public typealias ArrayClosure<T> = (array:[T]?) -> Void 

Daha sonra ArrayClosure<Int> gibi kullanmak. Ama şu anda yasal değil.

Bu tür takma adlar önermiyorum. Aydınlattıklarından daha fazlasını belirsizler.

func foo(onError: FailureClosure) 

ile: bu imzayı karşılaştırın

func foo(onError: NSError? -> Void) 

karakterden sadece birkaç kaydetmek için, ne FailureClosure geçer tahmin etmeye arayan zorlar. error veya progress etiketleri gerçekten size yardımcı olmuyor (progress in ...'u kullanmaya devam etmeniz gerekiyor).

anlamda çok etrafında progress olduğunu kılan tek olgu, ama istediğiniz türü yoktur düşünüyorum:

public typealias Progress = Float32 

, tip örtüşme çok yararlı olabilir burada beni yanlış anlamayın ne zaman Yeni bir tip oluşturur. Progress, float olarak uygulanacak bir türdür. Ama yaptığınız şeylerin çoğu (kesinlikle ArrayClosure ile ve diğerleri ile daha az ölçüde) yeni bir tür oluşturmadan yeni bir sözdizimi oluşturuyor ve bu da çoğu zaman yardımcı olmaktan çok kafa karıştırıcı. Bunun gerçekten karmaşık olduğu haklısın

func foo(failure: ((error: NSError?) ->())? = nil) 

: tipi takma aşırı tasarımınızı overcomplicate neden olabilir neden


özel örneğini aramak için,. Karşılaştırma:

func foo(failure: NSError -> Void = {_ in return}) 

Burada iki büyük değişiklik var. İsteğe bağlı bir hataya neden olan bir hata bloğuna sahip olmanıza gerek yoktur. Her zaman bir hata iletin (hata yoksa, neden failure çağrılmalıdır?). Ve başarısızlık bloğunun isteğe bağlı olması için bir sebep yok. Eğer gerçekten bir varsayılan değer istiyorsanız, sadece varsayılan değeri hiçbir şey yapmayın. İki isteğe bağlı gitti ve tüm tüketim ve uygulama kodları daha da basitleşiyor. Kesinlikle bir şeylerin isteğe bağlı olması gerekip gerekmediğini dikkatlice düşünün. İsteğe bağlı çok karmaşıklık katıyor; onları hafifçe eklemeyin.

Şahsen, muhtemelen yerine birçok durumda bir aşırı ile bu yapardım:

func foo(#failure: NSError -> Void) { ... } 

func foo() { 
    foo(failure:{ _ in return }) 
} 

ben sadece ne olup bittiğini anlamak için biraz daha kolay olduğunu düşünüyorum. Ama her iki yol iyidir.


DÜZENLEME (Aralık 2014): Bir kaç ay daha Swift yazdıktan sonra, aşağıda yorumlarda David'in yaklaşımı kapatılması için isteğe bağlı kullanımı @ daha düşkün büyüdü ama için ettik hata. Özellikle Swift'in isteğe bağlı zincirleme sözdizimi (failure?()) verildiğinde, çoğu zaman daha net olmak için rüzgar çıkıyor.

+0

Bunun için teşekkürler. Örneklerinizden, kapanışlar için tür takma adlarını kullanmanın temel olarak sadece yeni sözdizimi oluşturduğunu, kodun daha okunabilir hale getirdiğini düşünüyorum. Bu işlevi örneğin şu şekilde yapın: 'func foo (hata: ((hata: NSError?) ->())? = Nil)', burada ne olduğunu anlamak, tüm parantezleri ve sözdizimini belirtmek oldukça zordur. Bu yüzden bir 'typealias' kullanımı. Böyle bir yöntemi açıklamak için daha basit bir yöntem öneremezseniz. –

+0

Örneğinizde, isteğe bağlı olmaya gerek yoktur. Büyük olasılıkla burada varsayılan bir değer yerine aşırı yüklemeler kullanmanızı öneririm, ancak varsayılan değerinizi, özellikle de "Void" i döndürdüğü için hiçbir şey yapmayan bir kapatma işlemi yapabilirsiniz. Bu, sonraki kodunuzu da basitleştirecektir. Tipo-familyalar içindeki yuvalama şeyleri, bu tür karmaşık imzaları teşvik eder, bu da birçok durumda gerçekte kullanılması güçtür. (ObjC'de gerçekten karmaşık bloklarla bunu çok gördük.) –

+0

Çok karmaşık bir tipiniz varsa ve gerçekten bu türlere ihtiyacınız varsa ve bu tipi sık sık kullanıyorsanız, bunun bir takma ad oluşturmaya değer olduğu doğrudur. Ama bu normal düzeniniz olmamalı. Gördüğünüz gibi, bile çalışmadığı çok sayıda küçük köşe vakası içine giriyor. –