Swift 中的泛型 - “无法推断通用参数 'T' [英] Generics in Swift - "Generic parameter 'T' could not be inferred

查看:126
本文介绍了Swift 中的泛型 - “无法推断通用参数 'T'的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我想从一个方法返回一个符合 MyProtocolUIViewController,所以我使用了方法签名:

I'd like to return a UIViewController conforming to MyProtocol from a method, so I'm using the method signature:

func myMethod<T where T : UIViewController, T : MyProtocol>() -> T {

我不明白的第一件事:如果 myMethod 返回,例如必须遵循签名的 MyViewController,我必须强制转换它:

First thing I don't understand: if myMethod returns e.g. a MyViewController which has to following signature, I have to force cast it:

class MyViewController: UIViewController, MyProtocol

我不能简单地return MyViewController() 但我需要像这样转换它:return MyViewController() as!T - 为什么这是必要的?

I cannot simply return MyViewController() but I need to cast it like this: return MyViewController() as! T - why is this necessary?

第二件事:我如何在某处使用这种方法?我不能简单地说

And the second thing: how can I use this method somewhere? I cannot simply say

let x = myMethod() as? UIViewController

当我收到错误时

Generic parameter 'T' could not be inferred

我怎样才能实现这样的目标?如果我将它转换为 MyViewController 它可以工作,但我当然想避免这种情况.

How can I achieve something like this? If I cast it to MyViewController it works, but I would like to avoid that of course.

示例

class MyViewController : UIViewController, MyProtocol {
}

protocol MyProtocol {
}

func myMethod<T>() -> T where T : UIViewController, T : MyProtocol {
    return MyViewController() as! T // why is the cast necessary?
}

好的,我确实得到了一部分,但是为什么需要转换为 T ?MyViewControllerUIViewController 的子类,符合协议,所以不需要强制转换,对吧?

ok, I do get one part, but why is the cast to T necessary? MyViewController is a subclass of UIViewController and conforms to the protocol, so no cast should be necessary, right?

推荐答案

func myMethod<T where T : UIViewController, T : MyProtocol>() -> T

这个声明说:存在一个名为 myMethod 的函数,使得 myMethod 返回一些 specific T 其中TUIViewControllerMyProtocol 的子类型.这并没有说明T实际上是什么类型,也没有说只有一种这样的myMethod.如果有很多类型都是UIViewController 的子类并且符合MyProtocol,那么可以有很多.这些类型中的每一种都创建了一个新版本的 myMethod(对于 myMethod 所做的断言,确实存在这样的函数确实是一个新的解决方案).

This declaration says: There exists a function called myMethod, such that myMethod returns some specific T where T is a subtype of UIViewController and also MyProtocol. This does not say what type T actually is, and it does not say that there is only one such myMethod. There can be many if there are many type that are both subclasses of UIViewController and conform to MyProtocol. Every one of those types creates a new version of myMethod (really a new solution to the assertion myMethod makes, that such a function does exist).

这与以下不同:

func myMethod() -> UIViewController

也就是说:函数 myMethod 返回 UIViewController 的任何子类型.

That says: The function myMethod returns any subtype of UIViewController.

在 Swift 中没有办法表达任何类型是 UIViewController 的子类并且是 MyProtocol 的子类型".您只能讨论符合该标准的特定类型.Swift 不能以这种方式组合类和协议;这只是语言的当前限制,而不是深层设计问题.

There is no way in Swift to express "any type that is a subclass of UIViewController and is a subtype of MyProtocol." You can only discuss a specific type that meets that criterial. Swift can't combine classes and protocols this way; it's just a current limitation of the language, not a deep design issue.

特定任何是问题所在.有许多函数可以满足您的 myMethod 声明.您可以插入的每个符合规则的 T 都将成为候选者.因此,当您说 myMethod() 时,编译器不知道您指的是哪个特定的 T.

The specific versus any is the issue. There are many functions that satisfy your myMethod declaration. Every T you can plug in that conforms to the rules would be a candidate. So when you say myMethod(), the compiler doesn't know which specific T you mean.

(我打算扩展这个答案以提供更少的类型理论,更多的你如何在代码中做到这一点",但 donnywals 已经有一个很好的版本.)

(I was going to expand this answer to provide it in less type-theory, more "how do you do it in code" terms, but donnywals already has an excellent version of that.)

* 针对您编辑的问题 *

func myMethod<T>() -> T where T : UIViewController, T : MyProtocol {
    return MyViewController() as! T // why is the cast necessary?
}

T 是由调用者决定的特定类型.它不是任何符合的类型",而是符合某些特定的、具体的类型".考虑您调用的案例:

T is a specific type decided by the caller. It is not "any type that conforms" it is "some specific, concrete type that conforms." Consider the case that you called:

let vc: SomeOtherViewController = myMethod()

在这种情况下,TSomeOtherViewController.MyViewController 不是那种类型,所以你用 as! 演员做的事情是危险的.

In this case, T is SomeOtherViewController. MyViewController is not that type, so what you're doing with the as! cast is dangerous.

这篇关于Swift 中的泛型 - “无法推断通用参数 'T'的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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