Swift 中的泛型 - “无法推断通用参数 'T' [英] Generics in Swift - "Generic parameter 'T' could not be inferred
问题描述
我想从一个方法返回一个符合 MyProtocol
的 UIViewController
,所以我使用了方法签名:
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
?MyViewController
是 UIViewController
的子类,符合协议,所以不需要强制转换,对吧?
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
其中T
是 UIViewController
和 MyProtocol
的子类型.这并没有说明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()
在这种情况下,T
是 SomeOtherViewController
.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屋!