首页 文章

如何从通用函数返回值作为协议的实现?

提问于
浏览
3

我想为实现这些协议的对象构建协议映射 . 然后我希望能够获得给定协议的实现 .

这是我到目前为止所得到的:

class Services {
  var map = NSMapTable(keyOptions: .CopyIn, valueOptions: .WeakMemory)

  func register<T>(type: T, target: AnyObject) {
    map.setObject(target, forKey: String(type))
  }

  func get<T>(type: T) -> AnyObject {
    guard let target = map.objectForKey(String(type)) else {
      fatalError("Not registered")
    }
    return target
  }
}

我可以这样称呼它:

protocol Foo {
  func qux()
}

class Bar: Foo {
  func qux() {}
} 

services.register(Foo.self, target: Bar())

这太好了 . 但是当我想要检索它时:

let foo: Foo = services.get(Foo.self)

...以上行生成错误:

Foo.swift:12:34:无法将调用结果类型'AnyObject'转换为预期类型'Foo'

如何指定泛型函数 get 返回实现 T 中引用的协议的对象?

我想避免不得不接听电话 .

3 回答

  • 0

    我不确定这是否适合您的目的,但您可以这样写:

    class Services {
        var map = NSMapTable(keyOptions: .CopyIn, valueOptions: .WeakMemory)
    
        func register<T>(type: T.Type, target: T) {
            guard let object = target as? AnyObject else {
                fatalError("Cannot register")
            }
            map.setObject(object, forKey: String(type))
        }
    
        func get<T>(type: T.Type) -> T {
            guard let target = map.objectForKey(String(type)) as? T else {
                fatalError("Not registered")
            }
            return target
        }
    }
    
  • 0

    我知道你想避免垂头丧气,但我认为你应该使用:

    if let foo: Foo = services.get(Foo.self) as? Foo {
    
    }
    

    因为在你的情况下 protocol Foo: class 不起作用 .

  • 1

    如果让 get 返回泛型类型,你甚至不需要类型参数,因为你已经拥有它:

    func get<T>() -> T {
        guard let target = map.objectForKey(String(T.self)) else {
            fatalError("Not registered")
        }
        return target as! T // or you could make the return type an Optional if you want to allow getting a service that wasn't registered.
    }
    

    然后你可以像这样使用它:

    let foo: Foo = services.get()
    

相关问题