泛型类型约束与继承

时间:2015-03-26 17:12:03

标签: ios swift generics inheritance

这两个函数声明之间有区别吗?

func doSomething<T: UIViewController>(controller: T) {...}

VS

func doSomething(controller: UIViewController) {...}

Apples Swift programming language本书的类型约束语法部分中,有以下代码示例:

func​ ​someFunction​<​T​: ​SomeClass​, ​U​: ​SomeProtocol​>(​someT​: ​T​, ​someU​: ​U​) {
    // function body goes here
}

有了这个描述:

  

上面的假设函数有两个类型参数。第一个类型参数T有一个类型约束,要求T是SomeClass的子类。 ...

那么在哪种情况下使用上述通用功能会更好?

1 个答案:

答案 0 :(得分:5)

它们不同,但在你使用它们的方式上,它们几乎完全相同。

不同之处在于,当您调用泛型版本时,编译器将T静态设置为作为参数传入的任何类型。在对该参数调用方法时,这几乎没有任何区别 - 无论是对其方法的调用都将动态调度,并且您不能触及T的任何不保证可从约束中获得的部分。

但是假设您对此方法进行了更改,不仅仅是接受一个参数,而且返回一个类型相同:

// T here will take the type of whatever is going in/out of the function
// be that UIViewController or a subtype of it
func doSomethingGenerically<T: UIViewController>(controller: T) -> T {  
    // some logic that results in a new controller being returned
}

// here the return type is fixed to be UIViewController
func doSomethingViaBaseClass(controller: UIViewController) -> UIViewController {  
    // some logic that results in a new controller being returned
}

现在,假设你有一个UIViewController的子类,你就是这样传递的:

let subClass: MyUIViewController = ...

let controller1 = doSomethingGenerically(subClass)

let controller2 = doSomethingViaBaseClass(subClass)

此处,变量controller1的类型将为MyUIViewController,因为这是传递给函数的内容,因此Tcontroller2。但变量UIViewController的类型将为doSomethingViaBaseClass,因为这是{{1}}返回的固定类型。

注意,这并不意味着它们引用的对象将不同 - 这取决于函数体实现的内容。只是引用的变量的类型将会改变。

还有其他微妙的差异,但这是最需要了解的。然而,就结构而言,还有更多的差异需要注意。碰巧我昨天写了关于他们的an article,这可能有所帮助。