在swift协议中使用泛型函数或associatedType有什么区别?
protocol Repository {
associatedtype T
func add(data : T) -> Bool
}
和
protocol Repository {
func add<T>(data : T) -> Bool
}
答案 0 :(得分:4)
定义的关联类型使符合协议的类成为强类型。这样可以提供编译时错误处理。
另一方面,泛型使符合协议的类更加灵活。
例如:
protocol AssociatedRepository {
associatedtype T
func add(data : T) -> Bool
}
protocol GenericRepository {
func add<T>(data : T) -> Bool
}
class A: GenericRepository {
func add<T>(data : T) -> Bool {
return true
}
}
class B: AssociatedRepository {
typealias T = UIViewController
func add(data : T) -> Bool {
return true
}
}
类A
可以将任何类放入add(data:)
函数中,因此您需要确保该函数能够处理所有情况。
A().add(data: UIView())
A().add(data: UIViewController())
都是有效的
但是对于类B
,当您尝试放置除UIViewController
之外的任何内容时,都会出现编译时错误
B().add(data: UIView()) // compile-time error here
B().add(data: UIViewController())
答案 1 :(得分:3)
associatedtype
是struct / class中的静态类型,它通过typealias
声明或类型推断采用协议。该类的类型始终相同。
泛型可以是任何东西,甚至可以是同一类中的不同类型。
答案 2 :(得分:2)
这种情况
protocol Repository {
func add<T>(data : T) -> Bool
}
编译器将其理解为:“任何传递给func add
的类型都是可以接受的,该函数的结果将是Bool
”
但是这个
protocol Repository {
associatedtype T
func add(data : T) -> Bool
}
编译器将理解为:“ func add
仅接受typealias T = ...
中定义的类型并返回Bool
”
在第二种情况下,您仅将泛型参数限制为类型别名类型。
在协议的多个功能中使用通用参数时,将显示另一个重要功能。在这种情况下,它保证func add<T>
和func multiply<T>
具有相同的类型T
。如果是通用功能,则不能保证。
protocol Calculable {
associatedtype T
func add<T>(a: T, b: T) -> T
func multiply<T>(a: T, b: T) -> T
}
// In this case you know that T is the same for all functions
protocol CalculableDifferent {
func add<T>(a: T, b: T) -> T
func multiply<T>(a: T, b: T) -> T
}
// In this case add can accept One type, when multiply can accept Another