Weird Decoder behaviour with class inheritance

Can anybody help me to understand basic codable working with inheritance. Why if super class had conform to codable subclass object can't get initialise from JSON using jsonDecoder object?

    let string = """
    {
      "id": "1",
      "value": "Surya",
    }
    """
    class ID: Decodable {
    var id: String? = nil
   }
   class Name: ID {
      var value: String? = nil
   }

    let decoder = JSONDecoder()
    let json = Data(string.utf8)
    if let jsonObject = try? decoder.decode(Name.self, from: json) {
        print(jsonObject.id) // This initialize with Optional(1)
        print(jsonObject.value) // Why this is still nil
    }

Your issue has nothing to do with inheritance and Codable; you made Name.value a constant (let), and you initialized the constant to "" (empty string). Once you've initialized it, its value is set and can't be changed. Try removing the initialization of Name.value

Question updated. Thanks for point out but still getting nil value for subclassed variables. Is it is a bug in Swift ?

When I was looking at the Swift Language Reference, there is a paragraph about protocols and sub-classes. It implies that if you have a sub-class with a base class that conforms to a set of protocols, you have to repeat the conformance on the sub-class. So, in your case, the code would become:

class ID: Decodable {
...
}

class Name: ID, Decodable {
...
}

Note that the base class has to come first.

One thing for sure, is that re-conforming Name to Decodable won't compile. You'll simply get Redundant conformance of 'Name' to protocol 'Decodable'.

IIRC the compiler never synthesizes any implementations for any subclasses.

The behavior you're getting is instead due to Automatic Initializer Inheritance. Because all variables in Name has default value, Name inherits all initializers from its superclass, ID. This inheritance applies even to required initializers (see note on Required Initializer)

You'll need to override Name.init(from:) yourself. It's probably easier if you use struct instead of class.

3 Likes

This give the error of Redundant protocol conformance .

  1. Swift forbid conforming to the same protocol twice.
  2. Subclass inherits all protocol conformances.

So if you write

class ID: Decodable { ... }
class Name: ID { ... } // OK, `Name` conforms to `Decodable`

Name, which is a subclass of ID inherit Decodable conformance from ID.

If you write

class ID: Decodable { ... }
class Name: ID, Decodable { ... } // Error

Name conforms to Decodable twice, once from ID inheritance, again from explicit declaration right after ID, hence the error.

You can just try it out in playground and see.

Agree. Had seen :sunny:. Thanks for clarification :pray:

Terms of Service

Privacy Policy

Cookie Policy