我想从一个方法返回一个符合 MyProtocol
的 UIViewController
,所以我使用方法签名:
func myMethod<T where T : UIViewController, T : MyProtocol>() -> T {
第一件事我不明白:如果 myMethod
返回例如必须遵循签名的 MyViewController
,我必须强制转换它:
class MyViewController: UIViewController, MyProtocol
我不能简单地return MyViewController()
但我需要这样转换它:return MyViewController() as! T
- 为什么这是必要的?
第二件事:我怎样才能在某个地方使用这个方法?我不能简单地说
let x = myMethod() as? UIViewController
当我得到错误
Generic parameter 'T' could not be inferred
我怎样才能实现这样的目标?如果我将它转换到 MyViewController
它会起作用,但我当然想避免这种情况。
编辑:示例
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
的子类并且符合协议(protocol),所以不需要转换,对吧?
最佳答案
func myMethod<T where T : UIViewController, T : MyProtocol>() -> T
这个声明说:存在一个名为 myMethod
的函数,这样 myMethod
返回一些特定 T
其中T
是 UIViewController
和 MyProtocol
的子类型。这并没有说明 T
实际上是什么类型,也没有说明只有一个这样的 myMethod
。如果有很多类型都是 UIViewController
的子类并且符合 MyProtocol
,那么可以有很多。这些类型中的每一个都创建了一个新版本的 myMethod
(对于断言 myMethod
确实存在这样一个函数确实是一个新的解决方案)。
这不是一回事:
func myMethod() -> UIViewController
也就是说:函数 myMethod
返回 UIViewController
的任何子类型。
在 Swift 中没有办法表达“任何类型是 UIViewController 的子类并且是 MyProtocol 的子类型”。您只能讨论满足该标准的特定类型。 Swift 不能以这种方式组合类和协议(protocol);这只是语言的当前限制,而不是深层次的设计问题。
特定 与任何 是问题所在。有许多函数可以满足您的 myMethod
声明。您可以插入的每个符合规则的 T
都是候选者。所以当你说 myMethod()
时,编译器不知道你指的是哪个特定的 T
。
(我打算扩展这个答案,以更少的类型理论提供它,更多的是“你如何在代码中做到这一点”的术语,但 donnywals 已经有了一个很好的版本。)
* 针对您编辑的问题 *
func myMethod<T>() -> T where T : UIViewController, T : MyProtocol {
return MyViewController() as! T // why is the cast necessary?
}
T
是由调用者决定的特定类型。它不是“任何符合的类型”,而是“某种特定的、具体的符合类型”。考虑您调用的情况:
let vc: SomeOtherViewController = myMethod()
在这种情况下,T
是 SomeOtherViewController
。 MyViewController
不是那种类型,所以您使用 as!
强制转换是危险的。
关于ios - Swift 中的泛型 - 无法推断 "Generic parameter ' T',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38999102/