You can always make a macro to avoid boilerplate code, e.g.:
abstract type AbstractPerson end
mutable struct Person <: AbstractPerson
name::String
age::Int
end
macro inherit(name, base, fields)
base_type = Core.eval(@__MODULE__, base)
base_fieldnames = fieldnames(base_type)
base_types = [t for t in base_type.types]
base_fields = [:($f::$T) for (f, T) in zip(base_fieldnames, base_types)]
res = :(mutable struct $name end)
push!(res.args[end].args, base_fields...)
push!(res.args[end].args, fields.args...)
return res
end
@inherit Citizen Person begin
nationality::String
end
But honestly, I know very few tasks where field inheritance is indeed the best approach.