Search code examples
iosswiftgenericsswift2generic-programming

Factory in Swift using Generic Types


I'm trying to achieve the following in Swift - I want to pass in a type to a generic "get" function, and based on that type and the parameter, use different repositories to get back a class.

I recognize this is a bit strange to do in this way, but it would save me a lot of time and allow me to more properly refactor something later. Here is the code but it compile errors on the Foo1Repository and Foo2Repository lines "Cannot convert the type of Foo1Repository to T".

Basically Foo1Repository should return a Foo1, which inherits from BaseEntity of course (and the same is true for Foo2)

class func Get<T: BaseEntity>(id: Int) -> T
{
    if (T is Foo1) {
        return Foo1Repository.Get(id)
    }
    else if (T == Foo2) {
        return Foo2Repository.Get(id)
    }

    return T()
}

I was hoping to invoke this function by doing:

let foo = FactoryClass.Get<Foo1>(1)

I understand immediately you would ask "why not just call the appropriate repository, i.e."

let foo = Foo1Repository.Get(1) 

and you're all set! No need for some weird factory pattern here.

Let's just say at the moment I need to try to do it above without a lot of refactoring of some code I inherited. I'll get back to planning a proper refactor later.

So I've tried a combination of things but still can't seem to get past the compiler errors. Is something like this possible, or do I need to just bite the bullet and go a different route? Thanks so much!


Solution

  • So I figured it out! I wanted to share the answer so others can see how to do this. Hopefully it will help.

     func Get<T: BaseEntity>(id: Int) -> T
        {
            if (T.self == Foo1.self) {
                return Foo1Repository.Get() as! T
            }
            else if (T.self == Foo2.self) {
                return Foo2Repository.Get() as! T
            }
            ...
    
            return T()
        }
    

    So you can see, the whole as! T at the end was key. Also == instead of is for type checks.