Это неоднозначно, потому что Int
является как Hashable
, так и Comparable
, и ни один из этих двух протоколов не находится в одной иерархии. (Вы можете просмотреть 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'
Вы не можете явно указать, какие функции для вызова, из-за требований, связанных типа каждого протокола, но то, что вы можете сделать, это определить третью функцию :
func f<T: Comparable where T: Hashable>(t: T) {
println("Both Hashable & Comparable: \(t)")
}
f(number)
// Both Hashable & Comparable: 5
Это как Swift implements..<
оператор, который в противном случае был бы неоднозначным для типов, реализующих как Comparable
и ForwardIndexType
.
Чтобы расширить немного дальше, вот посмотрите на то, что я имел в виду «Вы не можете явно указать, какие функции для вызова из-за требований, связанных типа каждого протокола.» Протоколы могут быть использованы в качестве типов, как описано в книге Swift chapter on Protocols:
protocol RandomNumberGenerator {
func random() -> Double
}
class Dice {
let generator: RandomNumberGenerator
// ...
}
В этом примере свойство генератора может быть любого типа, который соответствует RandomNumberGenerator
- подобно тому, как id<ProtocolName>
используется в Objective-C. Однако протоколы могут использоваться только как типы, если они не включают связанный тип или ссылку Self
в свою декларацию. К сожалению, это исключает почти каждый встроенный тип Swift, включая Hashable
и Comparable
.
Hashable
наследует от Equatable
, который ссылается на Self
при определении ==
оператора:
func ==(lhs: Self, rhs: Self) -> Bool
и Comparable
делает то же самое с его операторами:
func <=(lhs: Self, rhs: Self) -> Bool
// similar definitions for <, >, and >=
Эти протоколы могут быть использованы только, как общие ограничения и не используются в качестве типа при объявлении переменной. (Насколько я могу судить, это недокументировано, но можно обнаружить через сообщения об ошибках.)
два протокола, которые сделать не есть, что ограничение является Printable
и BooleanType
, так что мы можем посмотреть, как они работают. Bool
является единственным встроенным типом, который соответствует BooleanType
, а также Printable
, так что это будет наш тип теста. Вот наши общие функции p()
и переменная t
- обратите внимание, что, как и прежде, мы не можем просто вызвать функцию с 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'
Вместо этого мы должны бросить (вентиляционный?) t
к определенному протоколу используя as
ключевое слово, и называть конкретную родовую функцию таким образом:
p(t as Printable)
// Printable: true
p(t as BooleanType)
// BooleanType: true
так что, пока у нас есть квалификационный протокол, мы можем выбрать, какой вариант универсального метода для вызова.
Работает ли 'job (myInt as Hashable)' работа? –
Nope :(Я получаю 2 ошибки: 'Протокол 'Hashable' может использоваться только как общее ограничение, потому что он имеет собственные или ассоциированные требования типа. И' Type 'Hashable' не соответствует протоколу 'Comparable'' (это один звучит странно :)) –
FYI для последней быстрой заметки эти два отличных ответа ... http://stackoverflow.com/a/39836054/294884 ... http://stackoverflow.com/a/39835658/294884 – Fattie