基于泛型类型的Swift泛型函数调用底层方法

Jer*_*rry 5 generics swift metatype

我正在为别人的代码 (SEC) 编写一个接口,我有一长串的功能或多或少是这样的:

public func readString(_ row: Row, columnName: String) -> String? {
    return SEC.getString(row, columnName)
}

public func readInt(_ row: Row, columnName: String) -> Int? {
    return SEC.getInt(row, columnName)
}
Run Code Online (Sandbox Code Playgroud)

等等。

我想做的是有一个功能:

public func read<T>(_ row: Row, columnName: String) -> T? {
    // call correct SEC.get* method
}
Run Code Online (Sandbox Code Playgroud)

我尝试了一个简单的 switch 语句 onT和 on T.Type,但没有骰子。我还尝试了上述的修改版本:

public func read<T: ReadableType>(_ row: Row, columnName: String) -> T? {
    let getter = T.getterMethod
    return getter(row, columnName)
}
Run Code Online (Sandbox Code Playgroud)

我可以在哪里创建一个enum具有SEC.get*函数的元类型,并扩展它以返回正确的 getter 方法。这对我来说似乎很理想。唉:

public enum ReadableTypes {
    case String.Type       // nope
    case Int.self          // also nope
}
Run Code Online (Sandbox Code Playgroud)

我不知道还能尝试什么;如果我只有十几个 read* 方法,那还不是世界末日,但是如果我能让它通用,调用这个方法的代码可能会非常紧凑。

小智 5

您可以单独测试以查看通用占位符代表什么类型,如下所示:

if T.self is Int.Type //...
Run Code Online (Sandbox Code Playgroud)

可以在switch..case语句中完成相同类型的测试。

假设SECSECType我要做的类型是扩展SECType到有一个通用get方法,它在返回类型上键入:

extension SECType {
  public func get<T>(_ row: Row, _ columnName: String) -> T? {
    // switch on the generic type
    switch T.self {
    // As much as I dislike force-unwrapping an Optional
    // this is about as safe as it gets.
    case is Int.Type   : return getInt   (row, columnName) as! T?
    case is String.Type: return getString(row, columnName) as! T?
    //...
    default: return nil
    }
  }
}
Run Code Online (Sandbox Code Playgroud)

现在您可以编写自己的read函数,例如:

public func read<T>(_ row: Row, columnName: String) -> T? {
  return SEC.get(row, columnName)
}
Run Code Online (Sandbox Code Playgroud)

当然,您可以跳过执行该操作,extension而只需使用switch. 但是,将方法添加到类型是无害的,并且类型具有这样的泛型方法是有意义的。

  • 非常酷,但请注意,OP 实际问题的答案只是短语“if T.self is Int.Type”。这就是他的谜题中缺失的部分——询问通用占位符已解析为的类型的语法。 (2认同)