代码之家  ›  专栏  ›  技术社区  ›  Jerry

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

  •  5
  • Jerry  · 技术社区  · 7 年前

    我正在为别人的代码(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
    }
    

    我试着打开了一个简单的switch语句 T T.Type ,但没有骰子。我还尝试了上面的修改版本:

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

    在那里我可以创建一个 enum 已经存在的元类型 SEC.get*

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

    我不知道还能尝试什么;如果我仅仅有十几个read*方法,这并不是世界末日,但是如果我能将其泛化,那么调用该方法的代码可能会非常紧凑。

    1 回复  |  直到 7 年前
        1
  •  5
  •   user887210 user887210    7 年前

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

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

    同样的测试可以在 switch..case 陈述

    假设 SEC 属于类型 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 . 然而,将方法添加到类型中是无害的,并且类型具有这样的泛型方法是有意义的。