2

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.

matt
  • 515,959
  • 87
  • 875
  • 1,141
  • Thanks for your concern. In effect, being a novice I struggled with the implementation of init(from: ), so I decided to simply make two classes instead of using iheritance. It's not optimum, but it works. :) – Luciano Falco Jan 30 '18 at 19:19
  • See now https://bugs.swift.org/browse/SR-6875 - The Swift team is on your side, but I don't think there's much they can do. You've just hit a spot where the language lets you down. – matt Jan 30 '18 at 19:38
  • I edited my answer to add an actual implementation of `init(from:)`. You tried to write this so you deserve some more help. :) – matt Jan 30 '18 at 19:45
  • Works like a charm. Thanks for your kind reply :) – Luciano Falco Jan 30 '18 at 20:13

2 Answers2

4

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)
    }
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
1

You need super.init in Pregunta and in PregRev put self.codAyuda = codAyuda before super.init

class PregRev: Pregunta {
    var codAyuda: String

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

    }
}
matt
  • 515,959
  • 87
  • 875
  • 1,141
Tigran
  • 235
  • 5
  • 14