Julia lets you define accessors later, e.g. if you rename the fields, you can still provide old names using getproperty()
:
struct Foo{T}
new_data::Vector{T}
new_ptrs::Vector{Int}
end
function Base.getproperty(foo::Foo, p::Symbol)
if p == :data
return getfield(foo, :new_data) # getfield() reads fields directly and it cannot be overloaded
elseif p == :ptrs
return getfield(foo, :new_ptrs)
else
return getfield(foo, p)
end
end
f = Foo([1,2,2,5,1,7],[1,3,6,7])
println(f.data)
println(f.ptrs)
Note that Julia compiler is smart enough to still translate simple getproperty()
calls into direct field pointers:
julia> using BenchmarkTools
julia> @btime $f.data;
1.753 ns (0 allocations: 0 bytes)
julia> @btime $f.new_data;
1.754 ns (0 allocations: 0 bytes)
There’s also Base.setproperty!()
for property mutation.