gpt4 book ai didi

generics - 了解快速泛型与将参数视为协议(protocol)或基本类型

转载 作者:搜寻专家 更新时间:2023-10-30 21:51:30 24 4
gpt4 key购买 nike

有人可以帮助我了解使用泛型比仅使用基类或协议(protocol)的好处吗?也许我只需要多读几遍 Swift 指南,但泛型的概念就是不深入。考虑这个使用泛型的例子

func removeObject<T : Equatable>(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 协议(protocol)的引用。

在实践中,差异几乎是不可察觉的。例如,如果您将 f 中的 t 传递给另一个函数,它的行为如下:

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

最大的区别在于它们可以返回实际的泛型类型而不是协议(protocol):

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

最后一个例子是理解为什么具有关联类型的协议(protocol)只能通用的关键。假设您想自己实现 first:

func first<C: CollectionType>(x: C) -> C.Generator.Element? {
if x.startIndex != x.endIndex {
return x[x.startIndex]
}
else {
return nil
}
}

如果 first 不是通用函数,而只是一个接收 CollectionType 协议(protocol)参数的常规函数​​,如何改变它返回的内容?

关于generics - 了解快速泛型与将参数视为协议(protocol)或基本类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/27629267/

24 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com