İşte

2017-01-08 54 views
5

aşırı daha spesifik bir yöntemi çağırmak için nasıl bir örnek oyun alanıdır.İşte

Herhangi bir sürümü test kaldırırsam, genel yöntem çağrılır. Sınıf Foo protokolü P protokolüne uygundur, neden daha spesifik olduğu için Swift jenerik yöntemi seçmiyor? Jenerik olanı aramanın bir yolu var mı?

+0

En basit çözüm, 'Any' aşırı yükünü' test etmek (_ :) 'jenerik - i.e' func test (_ o: T) '(bunun doğrudan sorunuzu yanıtlayıp yanıtlamadığından emin olmamak) olacaktır. – Hamish

+0

Genel yöntem bu durumda daha spesifik değil. Test (_ o: Any) 'argümanı, 'Foo' örneğini kendi argümanı olarak başarılı bir şekilde sarmalayabilen 'Any' (her birinin bir protokoldü olsa bile) 'in bir _koncrete type_'ından biridir. Herhangi bir beton türü, jenerik olandan daha spesifik olacaktır ve eski, "bar.test (...)" ifadesini çağırırken aşırı yüklenme çözünürlüğünden öncelikli olacaktır. Genel olarak 'Any' öğesini bir beton türü olarak kullanmaktan kaçınmalısınız ve daha iyi bir yaklaşım da alt katman olacaktır. Yukarıda @Hamish tarafından tanımlanan kısıtlanmamış jenerik ile (bu durumda kısıtlı jenerik daha spesifik olacaktır). – dfri

cevap

2

Anladığım kadarıyla, derleyici aşırı yük çözünürlüğü gerçekleştirirken genel olarak açıkça yazılan bir parametreyi tercih edecektir. Böylece, test<T : P>(_ o: T) ve test(_ o: Any) arasındaki çözünürlükte - ikincisi, açık (her ne kadar soyut) bir parametre tipine sahip olduğundan tercih edilirken, ilki sadece bir yer tutucudur. Eğer jenerik yanı ikinci aşırı yaparsanız

nedenle, derleyici şimdi ikisi de açıkça yazılan parametrenin olmaması gibi birinci aşırı lehine olacaktır, ancak ilk aşırı yük daha sıkı kısıtlanır:

class Bar { 
    func test<T: P>(_ o: T) { 
     print("Generic", o.getValue()) 
    } 

    func test<T>(_ o: T) { 
     print("Any") 
    } 
} 

let foo = Foo() 
let bar = Bar() 
bar.test(foo) // Generic hello 
Eğer irade aşırı hakkında daha iyi ikna etmeye izin verdiği

class Bar { 
    func test<T: P>(_ o: T) { 
     print("Generic", o.getValue()) 
    } 

    func test(_ o: Any) { 
     print("Any") 
    } 
} 

let foo = Foo() 
let bar = Bar() 
(bar.test as (Foo) -> Void)(foo) // Generic hello 

şiddetle, ilk yaklaşım öneriyoruz rağmen:

olduğu gibi aşırı yüklenmeleri tutulması, tip-döküm da belirginleştirmek için uygulanabilir bir çözüm gibi görünüyor seçilecek (jenerik Ayrıca, mümkün olan her durumda protokol tipi parametreler üzerinden de tercih edilmelidir, due to the performance benefits of specialisation).

+0

Tür olarak protokollerin genellikle soyut olarak değil, daha çok _nonspecific_ olarak adlandırıldığına inanıyorum. Muhtemelen, bu türden örneklere sahip olacağımızdan (sadece bunları genel türden yazanlar olarak kullanmamakla) önlenebilir. – dfri

+0

@dfri Huh, Onları her zaman soyut olarak ifade ettim (betonun zıddı olarak) - “bu türden örneklere sahip olmak” ile “bu şekilde yazılan bir örneğe sahip olmak” arasında küçük bir ayrım yapmak istiyorum. Protokol türlerine sahip olamazsınız, yalnızca protokol türleri olarak yazılan somut tür örneklerine sahip olabilirsiniz. Bu kesinlikle ilginç bir nokta olsa da, topluluk fikir birliğinin burada "soyut" kelimesinin kullanımıyla ilgilenmesiyle ilgilenecekti. – Hamish

+0

Farklılaşma ile doğru. İlgi çekici tartışmanın, soyut yazımcıların tanımını (genel tip sahibi, T, yukarıda veya typealias gibi) nasıl tanımlayacağına (ya da yapmayacağımıza), protokoller olarak yazılan örneklere (ikincisi, jenerik veya typealiases kullanmadan) ilişkili türler). Daha önce hiç olmadığı kadarıyla (Swift, özellikle) eskiden hızlı bir şekilde kullanılan dokümanlar için daha önce hiç görmediğim kadar soyut bir tepki vermişken, ikincisi için, en azından “Any” (yazılan), basit bir şekilde nonspesifik tip olarak tarif edilmiştir. dil rehberiAma belki de patates ve patates budur :) – dfri