具有子类类型的类方法调用闭包的基类

时间:2018-05-18 23:34:41

标签: swift generics

我有一个带有类func的基类:

class BaseModel
{
    class func getObjectWithId(_ id: String, completionHandler: @escaping (<???>) -> ())
    {
       // does query, calls completionHandler with matching object
    }
}

我有两个子课程:

class Cat: BaseModel { //whatever }
class Dog: BaseModel { //whatever }

我希望能够在子类上调用该类方法,并使用子类型的对象调用完成处理程序:

Cat.getObjectWithId("1") { (theCat) in
 // I want theCat to be of type Cat, not BaseModel
}

Dog.getObjectWithId("1") { (theDog) in
 // I want theDog to be of type Dog, not BaseModel
}

我修饰了仿制药,但承认这不是我的力量......

  • 我不想在每个基类中为此编写代码b / c除了类型之外它是相同的(即我不想要每个孩子必须实现的协议)。

  • 我不想要一个将类型作为参数的类方法。我真的非常喜欢我的示例方法调用的简单性。

2 个答案:

答案 0 :(得分:0)

您可以尝试以下代码:

class BaseModel
{
    class func getObjectWithId<T: BaseModel>(_ id: String, completionHandler: @escaping (T) -> ())
    {
       // does query, calls completionHandler with matching object
    }
}

但你必须明确地专门化这样的类型

Cat.getObjectWithId("1") { (theCat: Cat) in
    // I want theCat to be of type Cat, not BaseModel
}

Dog.getObjectWithId("1") { (theDog: Dog) in
    // I want theDog to be of type Dog, not BaseModel
}

但更安全的方法是在你想要的每个班级中复制函数getObjectWithId

答案 1 :(得分:0)

我最终在Anton的建议中采用了混合方法,并做了一些我原本不想做的事情:

  1. 我几乎完全像Anton一样创建了该方法的基本版本,除了它还需要数据类型(我最初想要避免的):

    class BaseModel
    {
        class func getObjectWithId<T: BaseModel>(_ id: String, type: T.Type, completionHandler: @escaping (T?) -> ())
        {
           // does query, calls completionHandler with matching object
        }
    }
    
  2. 子类具有自己的专用方法,可以调用该基类方法:

    class Dog: BaseModel
    {
        class func getDogWithId(_ dogId: String, completionHandler: @escaping (Dog?) -> ()
        {
            BaseModel.getObjectWithId(dogId, objectType: Dog.self) { (dog) in
            completionHandler(dog)
            }
        }
    }
    
  3. Con:在每个子类中为此方法创建签名很烦人(它甚至不再继承,但由于其他原因我仍然需要基类)。

    亲:很不错,因为我不必重复每个子课程中代码的内容,

    亲:每次调用子类方法时,我都不必投出结果。