基于类的泛型返回类型

时间:2017-04-13 16:00:53

标签: swift generics factory

我试图在一个类上创建工厂方法,该类自动转换为它所在的类。

extension NSObject {
    // how can I get the return type to be the current NSObject subclass
    // instead of NSObject?
    class func create() -> NSObject {
        return self.init()
    }

    // example: create(type: NSArray.self)
    class func create<T:NSObject>(type:T.Type) -> T {
        return T()
    }
}

示例2有效,但作为类方法没有优势:

let result = NSArray.create(type: NSArray.self) 

但我很乐意能够致电:

let result = NSArray.create() 

无需事后施放。有没有办法在Swift中做到这一点?

2 个答案:

答案 0 :(得分:4)

您可以使用班级Self

extension NSObject {
    class func create() -> Self {
        return self.init()
    }
}

let array = NSArray.create()

但我真的不明白你为什么会这么做,因为你也可以添加一个初始化器。

答案 1 :(得分:0)

接受的答案就是诀窍,谢谢!

但是,对于我没有直接调用init的情况,我需要这个。相反,我有一个NSObject类型的对象,需要强制向下转换

正如@Hamish从this other SO answer指出的那样,如果你是另一个深层(一个类方法调用的方法),你可以在类方法上使用泛型推理。

class func create() -> Self {
    return createInner()
}

class func createInner<T>() -> T {
    // upcasting to NSObject to show that we can downcast
    let b = self.init() as NSObject
    return b  as! T
}

let array = NSArray.create() // gives me an NSArray

CoreData的示例

我仍然无法弄清楚如何编译fetch部分,所以我仍在使用外部函数。

import CoreData

// callers use
// try fetch(type: SomeMO.self, moc: moc)
func fetch<T:NSManagedObject>(type:T.Type, moc:NSManagedObjectContext) throws -> [T] {
    return try T.fetch(moc: moc) as! [T]
}

extension NSManagedObject {
    class func makeOne(moc:NSManagedObjectContext) -> Self {
        return makeOneInner(moc: moc)
    }

    private class func makeOneInner<T>(moc:NSManagedObjectContext) -> T {
        let name = "\(self)"
        let retVal = NSEntityDescription.insertNewObject(forEntityName: name, into: moc)
        return retVal as! T
    }

    class func fetch(moc:NSManagedObjectContext) throws -> [NSManagedObject] {
        let fetchReq:NSFetchRequest<NSManagedObject> = self.fetchRequest() as! NSFetchRequest<NSManagedObject>
        let retVal = try moc.fetch(fetchReq) as [NSManagedObject]
        return retVal
    }
}