简体   繁体   English

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

[英]Swift generic function call underlying method based on generic type

I am writing an interface to Someone Else's Code (SEC), and I have a long list of functions more or less like this: 我正在为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)
}

And so on. 等等。

What I would like to do is have a single function: 我想做的是有一个功能:

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

I tried a simple switch statement on T and on T.Type , but no dice. 我在TT.Type上尝试了一个简单的switch语句,但没有骰子。 I also tried a modified version of the above: 我也试过上面的修改版:

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

Where I could create an enum of the metatypes that had SEC.get* functions, and extend it to return the proper getter method. 我可以在哪里创建具有SEC.get*函数的元类型的enum ,并扩展它以返回正确的getter方法。 This to me seemed ideal. 这对我来说似乎很理想。 Alas: 唉:

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

I'm not sure what else to try; 我不知道还有什么可以尝试的; it's not the end of the world if I simply have a dozen read* methods, but the code that calls this method could be so dang tight if I could make it generic. 如果我只是有十几个读取方法,那么这不是世界末日,但是如果我可以使它成为通用的话,那么调用这种方法的代码就会如此紧密。

You can individually test to see what type the generic placeholder represents like this: 您可以单独测试以查看通用占位符代表的类型:

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

The same sort of test can be done in a switch..case statement. 可以在switch..case语句中完成相同类型的测试。

Assuming SEC is of type SECType what I'd do is extend SECType to have a generic get method that keys on the return type: 假设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
    }
  }
}

Now you can write your own read function like: 现在您可以编写自己的read函数,如:

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

Of course you can skip doing the extension and just do a generic function with a switch . 当然,您可以跳过extension ,只需使用switch执行通用功能。 However, it's harmless to add the method to the type and it makes sense for the type to have a generic method like this. 但是,将该方法添加到类型中是无害的,并且类型具有这样的泛型方法是有意义的。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM