假设我有一个协议:
protocol Amazing {
func doAmazingStuff()
}
然后我有一个使用该类型执行操作的函数:
func doMoreCoolThings<T: Amazing>(awesome: T) -> T { ... }
它和做这样的事情有什么区别?
func doMoreCoolThings(awesome: Amazing) -> Amazing { ... }
我的问题是,为什么我们甚至会在使用泛型时烦恼呢?
更新 所以我可以看到使用遗传而不是:
的重点func doMoreCoolThings(awesome: Amazing) -> Amazing { ... }
然而,使用该功能真的有用吗?或者使用泛型总是更好吗?
答案 0 :(得分:3)
这只是我能立即想到的一个好处。我相信还有更多。
假设我们有两个类A
和B
,它们都符合Amazing
。
如果我们将A()
传递给此函数:
func doMoreCoolThings<T: Amazing>(awesome: T) -> T { ... }
像这样:
let val = doMoreCoolThings(awesome: A())
我们确信val
的类型为A
,编译器也知道这一点。这意味着我们可以使用A
访问val
个成员。
另一方面,如果我们将A()
传递给此函数:
func doMoreCoolThings(awesome: Amazing) -> Amazing { ... }
像这样:
let val = doMoreCoolThings(awesome: A())
val
的编译时类型为Amazing
。编译器不知道它是什么类型的Amazing
。它是A
还是B
还是其他?编译器不知道。您必须将结果转换为A
才能访问其成员。
let a = val as! A
演员也无法保证成功。
如果你把这些演员阵容放在哪里,你的代码很快就会变得非常混乱。
答案 1 :(得分:1)
您的问题包含错误的前提
func doMoreCoolThings(awesome: Amazing) -> Amazing { ... }
相当于:
func doMoreCoolThings<T: Amazing>(awesome: T) -> T { ... }
这根本不是真的。假设我有这些符合要求的类型:
struct AmazingApple: Amazing {
func doAmazingStuff() { print("I'm an apple who talks!") }
}
struct AmazingBanana: Amazing {
func doAmazingStuff() { print("I'm a banana who talks!") }
}
看看第一段代码让我做了什么:
func doMoreCoolThings(awesome: Amazing) -> Amazing {
return AmazingBanana()
}
let input = AmazingApple()
let result = doMoreCoolThings(awesome: input)
print("The input is of type \(type(of: input))")
print("The return is of type: \(type(of: result))")
参数类型和返回类型不同,即使它们都是Amazing
的两种子类型。
另一方面,看看当您尝试对通用变体执行相同操作时会发生什么:
泛型用于表达类型之间的关系。
非通用代码表示:
&#34;设doMoreCoolThings(awesome:)
为一个函数,它取一些类型为Awesome
子类型的值,并返回一个类型为Awesome
子类型的值。&#34; < / p>
通用代码表示:
&#34;设doMoreCoolThings(awesome:)
为一个函数,它取一些值,其类型是某种类型的子类型,称之为T
,并返回一个值,该类型是T
的子类型,其中T
本身是Amazing
的子类型。&#34;
请注意,第二个引号表示对参数的要求,并且返回属于同一类型。只有两者都是Amazing
的子类型是不够的。