在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
有人可以解释其背后的逻辑吗?
如果期望的返回值是'Generic',并且基本上返回的类型无关紧要,为什么编译器会抱怨呢?不铸就不行吗?
答案 0 :(得分:1)
泛型不是一些可以随时具有任何价值的神奇通配符。
当您致电itemForSelectedTabIndex(index: 0, type: Comment.self)
时,T
被推断为Comment
。同样,对于Other
。
将T
推断为Comment
时,T
的相同值在使用的所有位置都是一致的。因此,返回值必须为Comment
类型(或子类型)。
另一个与您的表情(type is Comment.Type) ? getComment() : getOther()
在一起。有2种情况,但都不有效:
type
为Comment.Type
:getComment()
返回Comment
,该类型与T
的值Comment
兼容。但是,条件运算符的两个操作数没有共同的超类型。那是无效的。type
是 not Comment.Type
:getOther()
返回一个Other
,它可能兼容也可能不兼容与T
。我们对T
所了解的只是它不是评论。这并不意味着它一定是Other
。它可以是任何其他类型,例如Int
。因此,此返回表达式失败。您需要的是您希望返回的两种类型的通用超类型。协议很可能是正确的选择(而不是共享的超类):
protocol TabItem {}
class Comment {}
class Other {}
func itemForSelectedTabIndex<T: TabItem>(index: Int, type: T.Type) -> TabItem {
return getCommentOrOtherOrSomethingElse()
}