Search code examples
swiftoopgenericsprotocols

Swift: Instantiate type <T> instance in a generic class


I want a generic class ClassA with a type T parameter that conforms to a specific protocol named ItemProtocol. I want to have an array of T inside the class, but the initialization of a T instance doesn't work. How should it be done?

protocol ItemProtocol: Codable {
    var itemId: String { get set }
    var parameter2: String { get set }
    var parameter3: String { get set }
}

struct Item: ItemProtocol {
    var itemId: String
    var parameter2: String 
    var parameter3: String
}

protocol AClassProtocol {
    associatedtype ItemProtocol

    func createItem() -> [ItemProtocol]
}

class ClassA<T: ItemProtocol>: AClassProtocol {
    private lazy var items = [T]()
    private func createItem() -> [T] {
        let newItem = T(itemId: "someDummyID", //Compilation error here
                        parameter2: "ABC",
                        parameter3: "BCA") 
        items.append(newItem)
        return items
    }
}

The compilation error I am receiving is: enter image description here


Solution

  • The problem is that T is ItemProtocol and ItemProtocol does not define any explicit initializers. Your code will compile if you add the following declaration to ItemProtocol:

    init(itemId: String, parameter2: String, parameter3: String)
    

    With that addition, the line:

    let newItem = T(itemId: "someDummyID",
                parameter2: "ABC",
                parameter3: "BCA")
    

    will compile as expected.

    Without that addition, the only init available via ItemProtocol is the init declared from the Decodable protocol that you get via Codable. That init is declared as init(from: Decoder) which is where the error about the missing from is being triggered.