Swift 基于类的泛型返回类型

Swift 基于类的泛型返回类型,swift,generics,factory,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: crea

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

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()
    }
}
但我希望能够打电话:

let result = NSArray.create() 

之后不必再投。在Swift中有什么方法可以做到这一点吗?

您可以使用类级别的
Self
来实现这一点:

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

let array = NSArray.create()

但是我真的不明白你为什么要这样做,因为你最好只添加一个初始值设定项。

你可以使用类级别的
Self
来实现这一点:

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

let array = NSArray.create()

但我真的不明白你为什么会这样做,因为你最好只添加一个初始值设定项。

接受的答案会起作用,谢谢

然而,在我没有直接调用
init
的情况下,我需要这样做。相反,我有一个类型为
NSObject
的对象,需要强制向下投射

正如@Hamish在中指出的,如果您在另一层(由类方法调用的方法)深处,则可以对类方法使用泛型推理


被接受的答案会起作用,谢谢

然而,在我没有直接调用
init
的情况下,我需要这样做。相反,我有一个类型为
NSObject
的对象,需要强制向下投射

正如@Hamish在中指出的,如果您在另一层(由类方法调用的方法)深处,则可以对类方法使用泛型推理


…你的意思是像初始值设定项一样?@Noah是的,在这个简化的示例中,init可以很好地工作,但实际上我自己从来没有调用过init。这只是为了说明……你是说像一个初始值设定项吗?@Noah是的,在这个简化的例子中,init可以很好地工作,但实际上我自己从来没有调用init。那只是为了说明。谢谢,我想我已经试过了。这对于
NSEntityDescription.insertNewObject
之类的东西很有用。所以这个问题是完整的,我接受这个答案。除此之外:我需要从我的通用
NSManagedObject
Self
并强制执行
as向下播放不起作用。嗯……@danrosenstack Compare@Hamish很吸引人,我不太理解类型推断,但我成功创建了一个工作示例。谢谢@Hamish和Noah。诺亚,我已经接受了你的答案,但你可以在下面看到我的答案和我的拍摄目的(当然,不知道具体说明)。谢谢,我想我已经试过了。这对于
NSEntityDescription.insertNewObject
之类的东西很有用。所以这个问题是完整的,我接受这个答案。除此之外:我需要从我的通用
NSManagedObject
Self
并强制执行
as向下播放不起作用。嗯……@danrosenstack Compare@Hamish很吸引人,我不太理解类型推断,但我成功创建了一个工作示例。谢谢@Hamish和Noah。诺亚,我已经接受了你的答案,但你可以在下面看到我的答案和我拍摄的目的(当然,不知道具体说明)。
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
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
    }
}