Search code examples
iosswiftgenericsprotocols

return protocol with associated type


how to return protocol with associated type?

protocol AProtocol {

}

class A: AProtocol {

}

class Main {
    func sendA() -> AProtocol {
        return A()
    }
}

it works.

but

protocol BProtocol {
    associatedtype B
}

class B: BProtocol {
    typealias B = Int
}

class Main {
    func sendA() -> AProtocol {
        return A()
    }

    func sendB() -> BProtocol { // error
        return B()
    }

// function1
    func sendB_<T: BProtocol>() -> T{
        return B() as! T
    }
}

i want to return 'return B()' in function 1 is it possible?


Solution

  • In this function

    func sendB_<T: BProtocol>() -> T{
        return B() as! T
    }
    

    you cannot return a B as a T because the person who uses the function defines what T is, not you and T can be any type that conforms to Protocol For example, I could do this:

    class C: BProtocol 
    {
        typealias B = Float
    }
    
    let c: C = Main().sendB_()
    

    By doing that, I am setting T to be a C and the forced typecast in sendB_() will fail.

    Unfortunately, protocols with associated types cannot, themselves, be treated like a concrete type, so the approach you took with AProtocol will not work.

    As I see it, you have two options. Change your function return type to B. After all, you always do return a B

    func sendB_() -> B {
        return B()
    }
    

    If you want to keep it generic, try

    protocol BProtocol 
    {
        associatedtype B
    
        init() // Needed to be able to do T() in generic function
    }
    
    func sendB_<T: BProtocol>() -> T{
        return T()
    }
    

    You need to add the initialiser to the protocol to make sure that an instance of type T always exists.