Jest to dwuznaczne, ponieważ Int
jest zarówno Hashable
i Comparable
, a żaden z tych dwóch protokołów nie jest w tej samej hierarchii. (Można wyświetlić Int
protocol hierarchy on Swifter.)
func f<T: Hashable>(t: T) {
println("Hashable: \(t)")
}
func f<T: Comparable>(t: T) {
println("Comparable: \(t)")
}
let number = 5
f(number)
// error: ambiguous use of 'f'
Nie można jednoznacznie powiedzieć to, jaką funkcję zadzwonić z powodu związanych z nimi wymagań typ każdego protokołu, ale co może nie jest zdefiniowanie trzeciej funkcji :
func f<T: Comparable where T: Hashable>(t: T) {
println("Both Hashable & Comparable: \(t)")
}
f(number)
// Both Hashable & Comparable: 5
ten sposób Swift implements operator ..<
, które w przeciwnym razie byłyby niejednoznaczne dla typów, które realizują zarówno Comparable
i ForwardIndexType
.
Aby rozwinąć trochę dalej, tu jest spojrzenie na to, co rozumie przez „nie można jednoznacznie stwierdzić, które funkcjonują go nazwać, z powodu związanych z nimi wymagań typ każdego protokołu.” Protokoły mogą być wykorzystane jako typy, jak opisano w książce chapter on Protocols Swift:
protocol RandomNumberGenerator {
func random() -> Double
}
class Dice {
let generator: RandomNumberGenerator
// ...
}
W tym przykładzie właściwość generator może być dowolnego typu, który jest zgodny z RandomNumberGenerator
- podobnie jak id<ProtocolName>
jest stosowany w Objective-C. Jednak protokoły mogą być używane jako typy, gdy nie zawierają skojarzonego typu lub odniesienia Self
w ich deklaracji. To niestety wyklucza prawie każdy wbudowany typ w Swift, w tym Hashable
i Comparable
.
Hashable
dziedziczy z Equatable
, które odniesienia Self
przy określaniu operatora ==
:
func ==(lhs: Self, rhs: Self) -> Bool
i Comparable
czyni to samo jej operacji:
func <=(lhs: Self, rhs: Self) -> Bool
// similar definitions for <, >, and >=
Protokoły te mogą jedyniesłużyć jako ogólne ograniczenia i nie są używane jako typ podczas deklarowania zmiennej. (O ile mogę powiedzieć, że jest to nieudokumentowane, ale można je wykryć za pomocą komunikatów o błędach.)
Dwa protokoły nie mają ograniczenie są Printable
i BooleanType
, więc możemy patrzeć na to, jak one działają. Bool
to jedyny wbudowany typ, który jest zgodny z BooleanType
i jest również Printable
, więc będzie to nasz typ testu. Oto nasze ogólne funkcje p()
i zmienna t
- zauważyć, że tak jak wcześniej, nie możemy po prostu wywołać funkcję z t
:
func p<T: Printable>(t: T) {
println("Printable: \(t)")
}
func p<T: BooleanType>(t: T) {
println("BooleanType: \(t)")
}
let t: Bool = true
p(t)
// error: Ambiguous use of 'p'
Zamiast tego, musimy oddać (uskok?) t
do określonego protokołu za pomocą słowa kluczowego as
i wywołać określoną funkcję Generic tamtędy:
p(t as Printable)
// Printable: true
p(t as BooleanType)
// BooleanType: true
tak długo, jak mamy protokół kwalifikacyjny, możemy wybrać, który wariant metody rodzajowe zadzwonić.
Czy "praca (myInt as Hashable)" działa? –
Nie :(Otrzymuję 2 błędy: "Protokół" Hashable "może być użyty tylko jako ogólne ograniczenie, ponieważ ma własne lub skojarzone wymagania typu" I "Hashable" typu "nie jest zgodny z protokołem" Porównywalny' (to jeden brzmi dziwnie :)) –
FYI na najnowszą szybką notatkę te dwie świetne odpowiedzi ... http://stackoverflow.com/a/39836054/294884 ... http://stackoverflow.com/a/39835658/294884 – Fattie