![](/img/trans.png)
[英]What is the in-practice difference between generic and protocol-typed function parameters?
[英]Difference between using Generic and Protocol as type parameters, what are the pros and cons of implement them in a function
由于Swift允许我们在函数中使用Protocol和Generic作为参数类型,因此我想到了下面的场景:
protocol AProtocol {
var name: String{ get }
}
class ClassA: AProtocol {
var name = "Allen"
}
func printNameGeneric<T: AProtocol>(param: T) {
print(param.name)
}
func printNameProtocol(param: AProtocol) {
print(param.name)
}
第一个函数使用generic作为带有类型约束的参数类型,第二个函数直接使用protocol作为参数类型。 但是,这两个函数可以产生相同的效果,这一点让我感到困惑。 所以我的问题是:
每种情况的具体情况是什么(或者只能通过特定情况而不是另一种情况进行的情况)?
对于给定的情况,两个函数都得出相同的结果。 哪一个更好实现(或者每个的优点和缺点)?
这个伟大的演讲提到了泛型专业化 ,这是一种优化,它将函数调度的方式从动态调度 (具有非泛型参数的函数)转变为静态调度或内联 (具有泛型参数的函数) 。 由于静态调度和内联与动态调度相比成本较低,因此使用泛型实现函数总能提供更好的性能。
@Hamish在这篇文章中也提供了很多信息,请查看更多信息。
这是一个新的问题来找我:
struct StructA: AProtocol {
var a: Int
}
struct StructB: AProtocol {
var b: Int
}
func buttonClicked(sender: UIButton) {
var aVar: AProtocol
if sender == self.buttonA
{
aVar = StructA(a: 1)
}
else if sender == self.buttonA
{
aVar = StructB(b: 2)
}
foo(param: aVar)
}
func foo<T: AProtocol>(param: T) {
//do something
}
实际上有一个来自今年WWDC的视频(关于类,结构和协议的性能;我没有链接,但你应该能够找到它)。
在第二个函数中,您传递符合该协议的任何值,实际上您传递的容器具有24个字节的存储空间用于传递的值,16个字节用于传递类型相关信息(以确定要调用的方法,ergo动态调度)。 如果传递的值现在大于内存中的24个字节,则对象将在堆上分配,容器存储对该对象的引用! 这实际上是非常耗时的,如果可能的话,当然应该避免。
在您使用泛型约束的第一个函数中,编译器实际上创建了另一个函数,该函数在该类型上显式执行函数的操作。 (如果你使用这个函数有很多不同的类型,你的代码大小可能会显着增加;请参阅C ++代码膨胀以供进一步参考。)但是,编译器现在可以静态调度方法,如果可能的话内联函数并确实不必分配任何堆空间。 在上面提到的视频中,代码大小不必显着增加,因为代码仍然可以共享...所以具有通用约束的函数肯定是要走的路!
现在我们有两个protocol
:
protocol A {
func sometingA()
}
protocol B {
func sometingB()
}
然后参数需要符合A
和B
//Generic solution
func methodGeneric<T:A>(t:T)where T:B {
t.sometingA()
t.sometingB()
}
//we need protocol C to define the parameter type
protocol C:A,B {}
//Protocol solution
func methodProtocol(c:C){
c.sometingA()
c.sometingB()
}
似乎没有错,但是当我们定义这样的结构时:
struct S:A,B {
func sometingB() {
print("B")
}
func sometingA() {
print("A")
}
}
方法methodGeneric
有效,但我们需要将struct S:A,B
更改为struct S:C
以使methodProtocol
有效。 一些问题:
protocol C
吗? func method(s:S)
那样写func method(s:S)
? 您可以在Generic Doc中阅读有关此内容的更多信息以获取更多信息。
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.