为什么在使用类型时使用泛型

时间:2017-07-30 05:24:42

标签: swift

假设我有一个协议:

protocol Amazing {
     func doAmazingStuff()
}

然后我有一个使用该类型执行操作的函数:

func doMoreCoolThings<T: Amazing>(awesome: T) -> T { ... }

它和做这样的事情有什么区别?

func doMoreCoolThings(awesome: Amazing) -> Amazing { ... }

我的问题是,为什么我们甚至会在使用泛型时烦恼呢?

更新 所以我可以看到使用遗传而不是:

的重点
func doMoreCoolThings(awesome: Amazing) -> Amazing { ... }

然而,使用该功能真的有用吗?或者使用泛型总是更好吗?

2 个答案:

答案 0 :(得分:3)

这只是我能立即想到的一个好处。我相信还有更多。

假设我们有两个类AB,它们都符合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的子类型是不够的。