polymorphic methods that return different class types in Swift?

432 views Asked by At

I have a collection of heterogeneous object types (common superclass). Per element, I want to fetch a class type to instantiate. In ObjectiveC, I did something like this:

@implementation CommonClass
- (Class) secondaryAnnotationClass {
    return [MKAnnotationView class]; // abstract implementation, just return default class
}
@end
@implementation SubclassFoo
- (Class) secondaryAnnotationClass {
    return [FooAnnotationView class]; // my specific annotation class
}
@end
@implementation SubclassBar
- (Class) secondaryAnnotationClass {
    return [BarAnnotationView class]; // my specific annotation class
}
@end

So what do I do to recreate this in Swift? I think it's something like the following, but I haven't yet done the right thing to make the compiler take the easy red dots away.

class CommonClass {
    var secondaryAnnotationClass:Type {
        return MKAnnotationView.self // abstract implementation, just return default class
    }
}
class SubclassFoo:CommonClass {
    var secondaryAnnotationClass:Type {
        return FooAnnotationView.self // my specific annotation class
    }
}
class SubclassBar:CommonClass {
    var secondaryAnnotationClass:Type {
        return BarAnnotationView.self // my specific annotation class
    }
}

It seems that to keep Swift's type system happy, what I really need to say is that I'll return not just a Type (is that really the replacement for Class?), but that it will be MKAnnotationView or one of its subclasses.

1

There are 1 answers

0
ABakerSmith On BEST ANSWER

You could have secondaryAnnotationClass return MKAnnotationView.Type:

class CommonClass {
    var secondaryAnnotationClass: MKAnnotationView.Type {
        return MKAnnotationView.self
    }
}

class SubclassFoo:CommonClass {
    override var secondaryAnnotationClass: MKAnnotationView.Type {
        return FooAnnotationView.self
    }
}

class SubclassBar:CommonClass {
    override var secondaryAnnotationClass: MKAnnotationView.Type {
        return BarAnnotationView.self
    }
}

With this approach, if you have methods or properties specific to FooAnnotationView or BarAnnotationView that you need to use, you'll have to downcast. For example:

class FooAnnotationView: MKAnnotationView {
    func myFunc() {
        print("Foo")
    }
}

let subclassFoo = SubclassFoo()
let annotation = subclassFoo.secondaryAnnotationClass() as! FooAnnotationView
annotation.myFunc() // Prints: "Foo"