【问题标题】:Swift protocol conformance when returning a generic返回泛型时的 Swift 协议一致性
【发布时间】:2020-08-04 16:24:34
【问题描述】:

这是一个例子:

protocol Feed {
    func items<T>() -> [T]? where T: FeedItem
}

protocol FeedItem {}

class FeedModel: Feed, Decodable {
    func items<T>() -> [T]? where T : FeedItem {
        return [FeedItemModel]() // Error: Cannot convert return expression of type '[FeedItemModel]' to return type '[T]?'
    }
}

class FeedItemModel: FeedItem, Decodable {}

为什么会这样:

A) 当T 是泛型而不是类型时,尝试转换为T? B) 不将FeedItemModel 识别为符合FeedItem

【问题讨论】:

  • Unerlated,但是拥有一个可选数组几乎从来都不是正确的方法——如果没有值就使用一个空数组。

标签: swift function generics protocols


【解决方案1】:
func items<T>() -> [T]? where T : FeedItem

这表示调用者可以将T 定义为他们想要的任何东西,只要T 符合FeedItemModel,并且此函数将返回一个可选数组。

FeedItemModel 是符合 FeedItem 的某种东西,但它不承诺是调用者请求的类型 T

例如,考虑:

class OtherModel: FeedItem {}

根据你的函数签名,我可以这样做:

let ms: [OtherModel]? = FeedModel().items()

但是您的函数不会将[OtherModel]? 返回给我。我怀疑您实际上并不是说这是通用的。我猜你的意思是:

func items() -> [FeedItemModel]?

或者可能

func items() -> [FeedItem]?

(虽然在做后一个之前我会非常努力地思考,并确保协议存在确实在这里做了有用的工作。)

【讨论】:

    【解决方案2】:

    一)

    T 一种类型,一种在运行时指定的同质具体类型。
    成像Tclass Foo : FeedItem 很明显FeedItemModel 不能转换成Foo

    B)

    FeedItemModel 被识别为符合 FeedItem 但这无关紧要。


    这通常是泛型和协议的混合。泛型类型不是协变的。如果您需要协变类型,请使用关联类型。

    【讨论】:

    • “运行时指定的类型”?我认为编译时
    • 不,它是在运行时指定的。在编译时,它是符合给定约束的 some 类型。
    【解决方案3】:

    您可以忽略泛型,因为它只适用于那个函数并且不需要它,因为直接说返回类型是 [FeedItem]? 会产生相同的结果

    protocol Feed {
        func items() -> [FeedItem]?
    }
    
    class FeedModel: Feed, Decodable {
        func items() -> [FeedItem]?  {
            return [OtherModel]()
        }
    }
    

    另一方面,如果您想要一个通用协议,那么您应该使用关联类型

    protocol Feed2 {
        associatedtype T: FeedItem
    
        func items() -> [T]?
    }
    
    class FeedModel2: Feed2, Decodable {
        typealias T = FeedItemModel
        func items() -> [T]?  {
            return [FeedItemModel]()
        }
    }
    

    【讨论】:

      猜你喜欢
      • 2021-10-13
      • 2015-09-07
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多