ios - Swift 中的泛型 - 无法推断 "Generic parameter ' T'

标签 ios generics swift3

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

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

好吧,我确实得到了一部分,但为什么必须转换为 TMyViewControllerUIViewController 的子类并且符合协议(protocol),所以不需要转换,对吧?

最佳答案

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

这个声明说:存在一个名为 myMethod 的函数,这样 myMethod 返回一些特定 T 其中TUIViewControllerMyProtocol 的子类型。这并没有说明 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()

在这种情况下,TSomeOtherViewControllerMyViewController 不是那种类型,所以您使用 as! 强制转换是危险的。

关于ios - Swift 中的泛型 - 无法推断 "Generic parameter ' T',我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/38999102/

相关文章:

ios - 以编程方式导航到手机上应用程序的推送通知设置

ios - 在 Swift 3 中将图像写入 SQLite

ios - 从 AppDelegate 呈现一个 ViewController,它显示出来但导航栏未激活,我无法从那里转换到任何其他 View

java - 在泛型 Java 类中对泛型变量使用数学运算符

java - 在 Java 中,如何实现返回 Class<List<String>> 的方法

java - 在具有泛型的方法中使用映射

ios - 如何使用MapKit在Swift 3中更改图钉颜色

ios - 后台问题中的 Apple 推送通知

ios - 在 iOS 中创建多步注册

iphone - 如何使用 NSInputStream 和 NSOutputStream 读写音频文件