Copying struct fields to another struct

For example I have an -

abstract type A

abstract type B <: A

struct C <: B
fields
end

Now, I want another struct D which has all fields of C but is a subtype of A i.e,

struct D <: A
C fields
end

Is there a way to do this, without manually copy pasting the contents ?

1 Like

No, at least not without macros. Copy and paste is honorable.

2 Likes

Is Mixers.jl what you want? And what about Classes.jl?

1 Like

Mixers.jl will work, but it ends up constructing a whole bunch of macros. I managed to build a single macro that does what I need it to do, and handles parametric types.

function get_type_expression(X::Union{Symbol,DataType})
    if X isa Symbol
        return X
    elseif X isa DataType
        Params = X.parameters
        if isempty(Params)
            return Symbol(X.name.wrapper)
        else
            return Expr(:curly, Symbol(X.name.wrapper), Params...)
        end
    end
end


macro inherit_fields(AssetTypeExp::Expr)
    BaseAssetType = Core.eval(@__MODULE__, AssetTypeExp.args[1])
    TypeSymbols   = AssetTypeExp.args[2:end]
    AssetType     = BaseAssetType{TypeSymbols...}

    ex = Expr(:block)
    for fName in fieldnames(AssetType)
        fType = fieldtype(AssetType, fName)
        fTypeParsed = get_type_expression(fType)
        push!(ex.args, :( $fName :: $fTypeParsed ) )
    end

    return esc(ex)
end

You can then use this macro pretty intuitively as follows:

mutable struct MyOldType{T}
    Name :: Symbol
    A :: T
    B :: T
    V :: Vector{T}
end

mutable struct MyNewType{T}
    @inherit_fields(MyOldType{T})
    C :: T
end

As you can see, it’s all done in one neat step without building a whole bunch of specific macros as you would do in Mixers.jl. You can even modify this by adding a second argument that lists fields you want to leave out of the inheritance and filtering those out of the for loop (keep in mind that the field array will be an expression so you will have to evaluate it to get an array of Symbols).

2 Likes