有人可以帮我理解使用泛型而不仅仅使用基类或协议的好处吗?也许我只需要阅读Swift指南几次,但泛型的概念并没有下沉.考虑使用泛型的这个例子
func removeObject(object: T, inout fromArray array: [T]) { var index = find(array, object) array.removeAtIndex(index!) }
为什么不这样写呢?
// As pointed out, this does not compile. I was more-so curious as to why func removeObject(object: Equatable, inout fromArray array: [Equatable]) { var index = find(array, object) array.removeAtIndex(index!) }
谢谢你的解释.
更新.是的,澄清我的例子完全是假设的.我正在考虑如何在Objective-C中实现这个问题.在那,我只是传递类型id的参数,这将做到这一点.
我的问题是为了深入了解为什么在Swift中不允许使用类似的模式,而是使用泛型来代替.
我认为Swift团队有一篇关于如何能够将第二个例子作为第一个例子的简写的开发论坛帖子.但是,我认为它仍然是一个通用函数 - 只是一个声明一个的简写?
那有什么不同?正如其他答案所指出的那样,Equatable
一般只能使用.但是,让我们举一个不必的例子.这怎么样:
func f<T: Printable>(t: T) { // do some stuff }
不同于此:
func g(p: Printable) { // do some stuff }
不同的是,f
定义了一系列的说是在编译时生成的函数,与任何作为什么是传递的类型t
取代T
.*所以,如果你在一个通过Int
,这将是,如果你会写一个版本func f(t: Int) { … }
.如果你通过了Double
,那就像写作一样func f(t: Double) { … }
*这是一个过度简化,但现在就用它...
另一方面,g
只有一个函数,在运行时只能接受对Printable
协议的引用.
在实践中,差异几乎是不可察觉的.例如,如果将t
内部传递f
给另一个函数,则其行为如下:
func f(i: Int) { // h doesn’t receive an Int // but a Printable: h(i as Printable) }
例如:
func h(i: Int) { println("An Int!") } func h(p: Printable) { println("A Printable!") } func f<T: Printable>(t: T) { h(t) } h(1) // prints "An Int!" f(1) // prints "A Printable!"
你可以通过很少的方式看到差异:
func f<T: Printable>(t: T) { println(sizeof(t)) } f(1 as Int8) // prints 1 f(1 as Int64) // prints 8
最大的区别是它们可以返回实际的泛型类型而不是协议:
func f<T: Printable>(t: T) -> T { return t } func g(p: Printable) -> Printable { return p } let a = f(1) // a is an Int let b = f([1]) // b is an [Int] let c = g(1) // c is a Printable let d = g([1]) // d is a Printable
最后一个示例是理解为什么具有关联类型的协议只能一般使用的关键.假设您想要自己实现first
:
func first<C: CollectionType>(x: C) -> C.Generator.Element? { if x.startIndex != x.endIndex { return x[x.startIndex] } else { return nil } }
如果first
不是泛型函数,只是一个接收CollectionType
协议参数的常规函数,那么如何改变它返回的内容呢?