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

时间:2017-09-16 03:01:20

标签: swift generics metatype

我正在为Someone Else的代码(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)
}

等等。

我想做的是有一个功能:

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

我在TT.Type上尝试了一个简单的切换声明,但没有骰子。我也试过了上面的修改版本:

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

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

public enum ReadableTypes {
    case String.Type       // nope
    case Int.self          // also nope
}

我不确定还有什么要尝试的;如果我只是有十几个读取*方法,那么这不是世界末日,但是如果我能将它变成通用的话,那么调用这种方法的代码就会非常紧张。

1 个答案:

答案 0 :(得分:3)

您可以单独测试以查看通用占位符所代表的类型:

if T.self is Int.Type //...

可以在switch..case声明中进行同样的测试。

假设SEC的类型为SECType,我要做的就是扩展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
    }
  }
}

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

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

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