首页 > 解决方案 > Swift Generic struct 符合与 associatedType 的协议得到“无法将'String'类型的返回表达式转换为返回类型'Key'”错误

问题描述

protocol Container {
    associatedtype ItemType
    func getItem() -> ItemType
    func getItems() -> [ItemType]
}

struct TypedBackpack<TypedItemType: StringProtocol>: Container {
    func getItem() -> TypedItemType {
        return ""
    }
    
    func getItems() -> [TypedItemType] {
        return [""]
    }
}

struct KeyBackpack<Key: Sequence>: Container {
    func getItem() -> Key { //"Error: Cannot convert return expression of type 'String' to return type 'Key'"
        return ""       
    }
    func getItems() -> [Key] { //"Error: Cannot convert return expression of type 'String' to return type 'Key'"
        return [""]
    }
}

对于 KeyBackPack 中的“getItem()”和“getItems()”函数,我得到“错误:无法将“String”类型的返回表达式转换为“Key”类型的返回表达式。但是,TypedBackPack 工作正常。

如果我将 KeyBackPack 更改为:

struct KeyBackpack<Key: StringProtocol>: Container {
    func getItem() -> Key {
        return ""       
    }
    func getItems() -> [Key] { 
        return [""]
    }
}

一切正常。所以问题是“<Key: Sequence>”。谁能告诉我为什么 <Key: StringProtocol> 工作正常但 <Key: Sequence> 不行?

标签: swiftgenericsprotocols

解决方案


根据您的声明,我可以使用 anySequence作为 的类型参数KeyBackpackgetItem并将返回该类型的实例。

所以理论上,我可以这样做:

let intArray = KeyBackpack<[Int]>().getItem()

[Int]如果明显 a SequencegetItem应该给我一个[Int]。但是,getItem实际返回的是一个空字符串!显然这没有意义!

那为什么会Key: StringProtocol起作用?

这是因为StringProtocol继承自ExpressibleByStringInterpolation,而后者又继承自ExpressibleByStringLiteral

这意味着您可以将字符串文字隐式转换为Key, 因为Key符合ExpressibleByStringLiteral.

更具体地说,从StringProtocol继承需求,编译器会自动转换为对该初始化程序的调用。您可以将其视为:init(stringLiteral:)ExpressibleByStringLiteralreturn ""

return Key(stringLiteral: "")

这也意味着,如果您返回字符串文字以外的内容,Key: StringProtocol则将无法正常工作。例如

let s = "" // here the type of "s" is inferred to be String 
return s // "cannot convert type..." error because "s" is not a string literal, nor of type "Key"

推荐阅读