首页 > 解决方案 > Swift 4,泛型为什么我需要在这里转换为 T ?

问题描述

在 Swift 4 中运行此代码时,编译器会抛出以下错误:

"Cannot convert return expression of type 'Comment?' to return type '_?', when running this code in a playground:
import UIKit

class Comment {}
class Other {}

func itemForSelectedTabIndex<T>(index: Int, type: T.Type) -> T? {
    return (type is Comment.Type) ? getComment() : getOther() 
}


func getComment() -> Comment {
    return Comment()
}

func getOther() -> Other {
    return Other()
}

let thing = itemForSelectedTabIndex(index: 0, type: Other.self)

为了完成这项工作,我需要将返回值转换为泛型,如下所示:

return (type is Comment.Type) ? getComment() as! T : getOther() as! T

有人可以解释这背后的逻辑吗?

如果预期的返回值是“通用”,基本上我返回什么类型都没有关系,为什么编译器会抱怨它?这不应该在没有铸造的情况下工作吗?

标签: swiftgenerics

解决方案


泛型不是一些在任何时候都可以具有任何价值的神奇通配符。

当你打电话时itemForSelectedTabIndex(index: 0, type: Comment.self)T是推断出来的Comment。同样,对于Other.

T被推断为Comment时,相同的值T在使用它的所有地方都是一致的。因此,返回值必须是类型Comment(或子类型)。

另一个是用你的表情(type is Comment.Type) ? getComment() : getOther()。有 2 种情况,但均无效:

  1. typeis Comment.TypegetComment()返回 a Comment,一个与 的值兼容的类型,TComment。但是,条件运算符的两个操作数没有共同的超类型。那是无效的。
  2. typeis not Comment.TypegetOther()返回一个Other,它可能兼容也可能不兼容T. 我们所知道T的是它不是评论。这并不意味着它是必然的Other。它可以是任何其他类型,例如Int. 因此,此返回表达式失败。

您需要的是您希望返回的两种类型的通用超类型。最有可能的是,协议是正确的选择(而不是共享超类):

protocol TabItem {}

class Comment {}
class Other {}

func itemForSelectedTabIndex<T: TabItem>(index: Int, type: T.Type) -> TabItem {
    return getCommentOrOtherOrSomethingElse()
}

推荐阅读