Seems like setproperty! is the way to go (using setfield! internally to avoid the stack-overflow).
E.g.
mutable struct Square
side
area
end
function Base.setproperty!(x::Square, field::Symbol, val)
if field == :side
setfield!(x, :side, val)
setfield!(x, :area, val^2)
else
# .. or whatever else you want to do here
error("oops!")
end
end
s1 = Square(2,4)
s1.side = 5
println(s1.area)
# output is 25
Alternatively, you could define a set of “derrived” properties that have no fields in the struct, and override propertynames and getproperty and use those to generate the derived properties.