gpt4 book ai didi

具有关联类型的 Swift 协议(protocol)(类型查找不明确)

转载 作者:搜寻专家 更新时间:2023-10-30 22:12:27 24 4
gpt4 key购买 nike

我需要在协议(protocol)中创建通用函数,在扩展中使用默认实现。它的功能应该与项目一起使用 enum:RawRepresentable where RawValue == String 始终。我试过了

protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable // how this add restriction to RawValue == String

func test<T: SectionIdentifierEnum>(identifier: T) where T.RawValue == String
}

enum RequiresEnumDefault: String {
case `default`
}

extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum.RawValue == String {

typealias SectionIdentifierEnum = RequiresEnumDefault

func test<T: SectionIdentifierEnum>(identifier: T) where T.RawValue == String {
print(T.rawValue)
}

}

但是我有错误

  • 'SectionIdentifierEnum' is ambiguous for type lookup in this context
  • 'RawValue' is not a member type of 'T'

任何解决方案

最佳答案

通常,当在协议(protocol)上下文中涵盖泛型时,泛型类型持有者被视为可由协议(protocol)的 associatedtype 表示。在您的示例中,这将是 SectionIdentifierEnum,它充当受限类型 的占位符。但是,SectionIdenfierEnum 本身并不是一个协议(protocol),因此不能将其用作泛型方法中的类型约束。但是,您可以test(...) 方法中将其用作类型本身。


swift 3.1

现在,目前(Swift 3.1),你不能添加复杂的类型约束到一个associatedtype。但是,您可以提供仅适用于 Self 派生自 UIViewController 并通过设置 RequiresEnum 协议(protocol)的情况的默认实现SectionIdentifierEnum 类型到具体的 RequiresEnumDefault 类型。后者将确定关联的 RawValue 是此默认实现的 String,作为具体 RequiresEnumDefaultRawValue类型是 String

例如:

// Swift 3.1
// ---------
// Types that implement this protocol mustn't necessarily use a
// `SectionIdentifierEnum` type where `SectionIdentifierEnum.RawValue`
// is constrained to equal `String`.
protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable

func test(identifier: SectionIdentifierEnum)
}

enum RequiresEnumDefault: String {
case `default`
}

// This extension, however, is only available for types that use
// `RequiresEnumDefault ` as the concrete type of `SectionIdentifierEnum`
// (in which case `SectionIdentifierEnum.RawValue` is `String`).
extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum == RequiresEnumDefault {

func test(identifier: SectionIdentifierEnum) {
print(identifier.rawValue)
}
}

// Example usage.
class MyViewController : UIViewController, RequiresEnum {
typealias SectionIdentifierEnum = RequiresEnumDefault
// ...
}

let foo = MyViewController()
foo.test(identifier: RequiresEnumDefault.default)
// prints "default" (using extension:s default implementation)

以上,test(...) 的默认实现仅在 SectionIdentifierEnum 等于具体类型 RequireEnumDefault(和 Self 派生自 UIViewController ...)。相反,如果您希望它仅在 SectionIdentifierEnumString 类型为 RawValue 的任何枚举时可用,您可以修改相应地扩展的类型约束:

protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable

func test(identifier: SectionIdentifierEnum)
}

enum RequiresEnumDefault: String {
case `default`
}

extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum.RawValue == String {

func test(identifier: SectionIdentifierEnum) {
print(identifier.rawValue)
}
}


// Example usage.
enum EnumWithStringRawValue: String {
case foo
}

class MyViewController : UIViewController, RequiresEnum {
typealias SectionIdentifierEnum = EnumWithStringRawValue
// ...
}

let foo = MyViewController()
foo.test(identifier: EnumWithStringRawValue.foo)
// prints "foo" (using extension:s default implementation)

一旦 Swift 4 发布,您将能够向 associatedtype:s 添加更复杂的约束,根据 Swift 演进提案的实现:

在这种情况下,上面的内容可以修改为:

// Swift 4
// -------
// Here, all types that implement this protocol must use a
// `SectionIdentifierEnum` type where `SectionIdentifierEnum.RawValue`
// is equal to `String`.
protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable
where SectionIdentifierEnum.RawValue == String

func test(identifier: SectionIdentifierEnum)
}

enum RequiresEnumDefault: String {
case `default`
}

// For the specific case where `SectionIdentifierEnum` equals
// `RequiresEnumDefault` (and where `Self` derives from `UIViewController`),
// this default implementation is readily available.
extension RequiresEnum where Self: UIViewController, SectionIdentifierEnum == RequiresEnumDefault {

func test(identifier: SectionIdentifierEnum) {
print(identifier.rawValue)
}

}

// Example usage.
class MyViewController : UIViewController, RequiresEnum {
typealias SectionIdentifierEnum = RequiresEnumDefault
// ...
}

let foo = MyViewController()
foo.test(identifier: RequiresEnumDefault.default)
// prints "default" (using extension:s default implementation)

同样修改 test(...) 的默认实现的约束不仅适用于 SectionIdentifierEnum 等于 RequiresEnumDefault 的情况(而且任何枚举:在这种情况下,我们知道这样的枚举总是有一个 RawValue String,因为协议(protocol)定义中对 associatedtype 的约束).

protocol RequiresEnum: class {
associatedtype SectionIdentifierEnum: RawRepresentable
where SectionIdentifierEnum.RawValue == String

func test(identifier: SectionIdentifierEnum)
}

enum RequiresEnumDefault: String {
case `default`
}

// From the constraint on the `RawValue` of `SectionIdentifierEnum`
// above, we know that `RawValue` equals `String`.
extension RequiresEnum where Self: UIViewController {

func test(identifier: SectionIdentifierEnum) {
print(identifier.rawValue)
}
}

// Example usage.
enum EnumWithStringRawValue: String {
case foo
}
class MyViewController : UIViewController, RequiresEnum {
typealias SectionIdentifierEnum = EnumWithStringRawValue
// ...
}

let foo = MyViewController()
foo.test(identifier: EnumWithStringRawValue.foo)
// prints "foo" (using extension:s default implementation)

关于具有关联类型的 Swift 协议(protocol)(类型查找不明确),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45356620/

24 4 0