泛型类型约束与继承 [英] Generics type constraint vs inheritance

查看:137
本文介绍了泛型类型约束与继承的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

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

vs。

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

类型约束语法部分rel =

  func someFunction< T:SomeClass,U:SomeProtocol>(someT:T,someU:U){
//函数体到这里
}

以下描述:


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

所以在哪种情况下使用上述泛型函数更好?



不同之处在于,当您调用通用版本时,编译器将静态设置为 T 作为参数传入的任何类型。当调用该参数的方法时,这几乎没有区别 - 无论哪种方式,其方法上的调用都将被动态分配,并且不能触及 T 保证可以从约束中获得。但是假设你对这个方法做了一个改变,不仅仅是接受一个参数,而且还有一个同样类型的 return ,: p>

  // T这里将取出函数
//进入/离开的类型//是UIViewController还是它的一个子类型
func doSomethingGenerically< T:UIViewController>(controller:T) - > T {
//一些导致新控制器被返回的逻辑
}

//这里返回类型被固定为UIViewController
func doSomethingViaBaseClass(controller :UIViewController) - > UIViewController {
//导致新控制器被返回的一些逻辑
}



<现在,假设你有一个你传入的 UIViewController 的子类,如下所示:

  let subClass:MyUIViewController = ... 

let controller1 = doSomethingGeneically(subClass)

let controller2 = doSomethingViaBaseClass(s​​ubClass)

这里,变量 controller1 的类型是 MyUIViewController ,因为那是传递给函数的,所以 T 是。但是变量 controller2 的类型将会是 UIViewController ,因为这是 doSomethingViaBaseClass的固定类型返回。



请注意,这并不意味着它们的参考对象会有所不同 - 这取决于什么函数的主体实现。它只是引用的变量类型,它会改变。



还有其他细微差别,但这是主要了解的。然而,就结构而言,还有更多值得注意的差异。碰巧我昨天写了一篇关于他们的文章,帮助。

Is there a difference between these two function declarations?

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

vs.

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

In Type Constraint Syntax section of the Apples Swift programming language book, there's this code sample:

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

with this description:

The hypothetical function above has two type parameters. The first type parameter, T, has a type constraint that requires T to be a subclass of SomeClass. ...

So in which cases is it better to use generic function described above?

解决方案

They are different, but in the way you are using them, they amount to pretty much exactly the same result.

The difference is that when you call the generic version, the compiler sets T statically to be whatever type is passed in as the argument. When calling methods on that argument, this makes almost no difference – either way the calls on its methods will be dynamically dispatched, and you can't touch any parts of T that aren't guaranteed to be available from the constraint.

But suppose you made a change to this method to not just take an argument, but also return one, of the same type:

// 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
}

Now, suppose you had a subclass of UIViewController that you were passing in, like so:

let subClass: MyUIViewController = ...

let controller1 = doSomethingGenerically(subClass)

let controller2 = doSomethingViaBaseClass(subClass)

Here, the type of the variable controller1 will be MyUIViewController, because that is what was passed in to the function so that is what T is. But the type of the variable controller2 will be UIViewController because that is the fixed type that doSomethingViaBaseClass returns.

Note, this doesn't mean the object they reference will be different - that depends on what the body of the function implements. It's just the type of the variables referring to it that will change.

There are other subtle differences but this is the main one to know about. In the case of structs, however, there are more differences worth noting. As it happens I wrote an article about them yesterday that might help.

这篇关于泛型类型约束与继承的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆