AamirR
AamirR

Reputation: 12218

Use class as generic type parameter in a method

I am using following generic method to return child classes

class SomeClass {

    var childInstance: ParentClass?

    func getClass<T: ParentClass>() -> T? {
        return childInstance as? T
    }

    func usage() {
        if let view: ChildTwo = self.getClass() {
            view.someMethodOfClassTwo()
        }
    }
}

Is it possible to pass class as generic type parameter? so the usage would be without if statement, like so:

self.getClass(type: ChildTwo)?.someMethodOfClassTwo()

Parent/child classes used above are as following:

class ParentClass { }
class ChildOne: ParentClass {
    func someMethodOfClassOne() { }
}
class ChildTwo: ParentClass {
    func someMethodOfClassTwo() { }
}

Update: ParentClass is a class, for some reason I cannot use a protocol or change it to a protocol.

Upvotes: 0

Views: 291

Answers (1)

nayem
nayem

Reputation: 7605

Yes you can. But I'm confused how you are going to use that.

You need to slightly modify the signature of your getClass<T: ParentClass>() -> T? function. I've purposefully changed the name of the function too because it doesn't make sense to have a name as getClass where you are actually getting child instance.

class SomeClass {

    var childInstance: ParentClass?

    func getChild<T: ParentClass>(type: T.Type) -> T? {
        return childInstance as? T
    }

    func usage() {
        if let child = self.getChild(type: ChildTwo.self) {
            child.someMethodOfClassTwo()
        }
    }
}

Again you can use it without the if-let binding too. But then you've to deal with optional chaining:

SomeClass().getChild(type: ChildTwo.self)?.someMethodOfClassTwo()

Here with ParentClass as a class, you get autocompletion as you pass a generic class type which actually doesn't make much of sense: ParentClass as class


Edit:

If you slightly modify the design as ParentClass to be a Parent protocol, then Xcode autocompletion will suggest you more meaningful signature. See:

protocol Parent { }
class ChildOne: Parent {
    func functionOfChildOne() { }
}
class ChildTwo: Parent {
    func functionOfChildTwo() { }
}

class SomeClass {

    var childInstance: Parent?

    func getChild<T: Parent>(type: T.Type) -> T? {
        return childInstance as? T
    }

    func usage() {
        if let child = self.getChild(type: ChildTwo.self) {
            child.functionOfChildTwo()
        }
    }
}

And Xcode autocomplete suggests you pass a type that conforms to Parent protocol Parent as protocol

Upvotes: 2

Related Questions