如何在Swift中创建通用的便利初始化程序?

Tom*_*ulc 7 generics swift

我正在使用Swift中的泛型.我有NSManagedObject类的扩展,并希望创建初始化程序,它只适用于实现我定义的某些协议的类.现在我有类似下面的东西,但这不起作用,甚至没有编译.你能帮我把它搞定吗?

public extension NSManagedObject {
    public convenience init<Self: Nameable>(context: NSManagedObjectContext)     {
        let entity = NSEntityDescription.entityForName(Self.entityName(), inManagedObjectContext: context)!
        self.init(entity: entity, insertIntoManagedObjectContext: context)
    }
}

public protocol Nameable {
    static func entityName() -> String
}
Run Code Online (Sandbox Code Playgroud)

Xcode说:"函数签名中没有使用通用参数'Self'".

Mar*_*n R 12

正如matt已经解释的那样,您无法定义仅限于实现协议的类型的初始化程序.或者,您可以改为定义全局函数:

public protocol Nameable {
    static func entityName() -> String
}

func createInstance<T : NSManagedObject>(type : T.Type, context : NSManagedObjectContext) -> T where T: Nameable {
    let entity = NSEntityDescription.entity(forEntityName: T.entityName(), in: context)!
    return T(entity: entity, insertInto: context)
}
Run Code Online (Sandbox Code Playgroud)

然后用作

let obj = createInstance(Entity.self, context)
Run Code Online (Sandbox Code Playgroud)

避免额外的类型参数如果你定义的方法

func createInstance<T : NSManagedObject>(context : NSManagedObjectContext) -> T where T: Nameable { ... }
Run Code Online (Sandbox Code Playgroud)

并用它作为

let obj : Entity = createInstance(context)
Run Code Online (Sandbox Code Playgroud)

要么

let obj = createInstance(context) as Entity
Run Code Online (Sandbox Code Playgroud)

现在从上下文推断出类型.

  • 我喜欢将占位符设置为返回类型的技巧,以避免将其实例作为参数传递,就像我在回答中所做的那样。我需要更频繁地使用这个技巧!:) (2认同)