【问题标题】:Return generic CaseIterable-conforming type from function从函数返回符合 CaseIterable 的通用类型
【发布时间】:2019-01-28 10:58:19
【问题描述】:

我正在尝试实现一个协议,该协议需要一个函数,该函数应返回符合CaseIterable 的类型的Type。当我调用该函数时,我希望能够在返回的泛型类型上调用 .allCases。不幸的是,编译器不允许我这样做。

protocol FooDataSource: class {
    func caseIterable<T: CaseIterable>(for foo: Foo) -> T.Type
}

class Foo {
    weak var dataSource: FooDataSource?

    func callAllCasesProperty() {
        let a = self.dataSource?.caseIterable(for: self).allCases
    }
}

当试图在操场上运行该代码时,我得到:

错误:experiments.playground:7:58:错误:无法推断通用参数Tlet a = self.dataSource?.caseIterable(for: self).allCases

有没有办法实现预期的功能?

【问题讨论】:

  • Swift 应该如何推断T 的类型?您绝对没有提供任何相关信息。
  • 假设我只想调用.allCases.count,编译时需要知道类型吗?
  • .allCases.count 什么?如果您想知道 something 有多少个 case,则必须指定该 something。例如,你不能测量一些现实生活中物体 X 的长度或重量,除非你有它,对吗?你不能把它抽象掉。
  • 我明白你的意思。如果您认为该问题有效,您介意添加答案吗?
  • 您需要协议吗?泛型函数似乎与协议无关。

标签: swift generics enums swift-protocols


【解决方案1】:

虽然我不确定您要完成什么,但看起来您可以使用对类型有一些特定约束的泛型函数。通过将 T 限制为 RawRepresentable 和 CaseIterable,您可以将枚举类型作为参数传递并在函数中调用 allCases。

enum Direction: String, CaseIterable {
    case north
    case south
    case east
    case west
}

enum Weight: Int, CaseIterable {
    case Light = 1
    case Mid = 4
    case Heavy = 10
}

func genericMethod<T : RawRepresentable & CaseIterable>(enumType: T.Type) {
    for aCase in enumType.allCases {
        print(aCase.rawValue)
    }
}

genericMethod(enum: Direction.self) // prints -> north, south, east, west
genericMethod(enum: Weight.self) // prints -> 1, 4, 10

您还可以像这样进一步限制类型 T:

func genericMethodWithRawConstraint<T : RawRepresentable & CaseIterable>(enumType: T.Type) where T.RawValue == String {
    for aCase in enumType.allCases {
        print(aCase.rawValue)
    }
}

//Will not compile because Weight is of type Int
//genericMethodWithRawConstraint(enum: Weight.self) 

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多