Search code examples
swiftdesignated-initializer

How to declare a subclass designated initializer with more parameters than superclass?


I'm making a subclass designated initializer with an extra parameter compared to the initializer from the superclass, however, i get an error. The code is:

class Pregunta: Codable {
    var codImagen: String
    var respCorrecta: Int
    var respUsuario = -1

    init(codImagen:String, respCorrecta:Int){
        self.codImagen = codImagen
        self.respCorrecta = respCorrecta
    }
}

class PregRev: Pregunta {
    var codAyuda: String

    init(codImagen:String, respCorrecta:Int, codAyuda: String){
        super.init(codImagen: codImagen, respCorrecta: respCorrecta)
        self.codAyuda = codAyuda
    }
}

And I get the error

'required' initializer 'init(from:)' must be provided by subclass of 'Pregunta'

What's the problem? I read that I just had to use a super.init with a superclass initializer. Thanks in advance.


Solution

  • This has nothing to do with your implementation of init(codImagen:String, respCorrecta:Int, codAyuda: String) (though that implementation is in fact wrong). It has to do with the fact that your superclass has adopted Codable.

    Codable requires an implementation of init(from:). Your superclass inherits this through a protocol extension, so there's no problem about the fact that you have not supplied an implementation.

    But the subclass is another story. By creating a designated initializer in the subclass, you have killed inheritance. Therefore, your subclass does not inherit the implementation of init(from:) from the superclass. Therefore you must supply it explicitly in the subclass:

    class Pregunta: Codable {
        var codImagen: String
        var respCorrecta: Int
        var respUsuario = -1
    
        init(codImagen:String, respCorrecta:Int){
            self.codImagen = codImagen
            self.respCorrecta = respCorrecta
        }
    }
    
    class PregRev: Pregunta {
        var codAyuda: String
        enum CodingKeys : String, CodingKey {
            case codAyuda
        }
        init(codImagen:String, respCorrecta:Int, codAyuda: String){
            self.codAyuda = codAyuda
            super.init(codImagen: codImagen, respCorrecta: respCorrecta)
        }
        required init(from decoder: Decoder) throws {
            let con = try decoder.container(keyedBy: CodingKeys.self)
            self.codAyuda = try con.decode(String.self, forKey: .codAyuda)
            try super.init(from:decoder)
        }
    }