There are a few motivations here:
1) Less boilerplate code (this can be written inline)
2) It's possible to provide multiple constructors for different packet variations to reduce the chance of errors.
3) It makes things catch fire on updates in ways that static analysers can understand.