将AnyObject作为Swift 4中的通用T参数传递

时间:2018-03-23 14:05:32

标签: ios swift generics swift4

我有一个有趣的问题:

class ListCache {

    public func getCachedList<T: Codable>() -> [T]? {
        //loads list from file cache using Codable
    }

}

让我说我有Foo课程:

class Foo: Codable {
    var bar = ""
}

现在,我可以这样做:

let array: [Foo] = ListCache().getCachedList()

但我做不到这样的事情:

var listsToLoad: [AnyClass] = [Foo.self]
let clazz = listsToLoad[0]
let array: [Codable] = ListCache().getCachedList()

编译器给我一个错误:

  

无法明确专门化通用函数

这意味着我无法在循环中调用getCachedList()因为我必须明确地给它一个类类型。

有没有办法实现这个目标?我也尝试过使用泛型类,但我几乎都是在同一点上结束。

编辑:

我尝试过创建:

class CodableClass: Codable {

}

然后:

class Foo: CodableClass {
    //...
}

现在编译器说clazz未声明:

var listsToLoad: [CodableClass.Type] = [Foo.self]
for clazz in listsToLoad {
    if let array: [clazz] = ListCache().getCachedList() {
        print(array.count)
    }
}

我也尝试了clazz.Typeclazz.self

2 个答案:

答案 0 :(得分:3)

我很确定为了调用泛型函数,必须在编译时知道该函数的参数类型。由于[Foo]实际上只是Array<Foo>的简写,因此也适用于类型化数组(尝试编写Array<clazz>;它不会编译)。因此,当你在clazz变量中有一个类型,这样实际的类只能在运行时知道,你不能用它来调用泛型函数,也不能声明一个类型的数组。

AFAIK,唯一的解决方案是:

  1. 使用[Codable]或<:p>

  2. 找到一种方法来动态执行您想要做的事情,Objective-C风格
  3. 找到另一种方法来做你想做的事: - (

  4. 由于我不知道你最终想要做什么,不幸的是,很难超越这一点。

答案 1 :(得分:0)

你可以试试

吗?
class ListCache {

  public func getCachedList<T: Cachable>() -> [T] {
    return [(Foo() as! T)]
  }

}

protocol Cachable: Codable { }

class CachableClass: Cachable {
  class func test() -> String {
    return "blo"
  }
}

extension Cachable {

  static func cachedValues() -> [Self] {
    return cachedValuesTemplate(type: self)
  }

  private static func cachedValuesTemplate<T: Cachable>(type: T.Type) -> [T] {
    return ListCache().getCachedList()
  }

}

class Foo: CachableClass { }

var listsToLoad: [CachableClass.Type] = [Foo.self]
for clazz in listsToLoad {
  print(clazz.cachedValues().count)
}