fields
sono semplicemente i "componenti" di una struttura. La struttura
struct A
b
c::Int
end
ha i campi b
e c
. Una chiamata per getfield
restituire l'oggetto associato al campo:
julia> a = A("foo", 3)
A("foo", 3)
julia> getfield(a, :b)
"foo"
Nelle prime versioni di Julia, la sintassi a.b
utilizzata per "abbassare", ovvero essere la stessa della scrittura getfield(a, :b)
. Ciò che è cambiato ora è che si a.b
riduce a getproperty(a, :b)
con il fallback predefinito
getproperty(a::Type, v::Symbol) = getfield(a, v)
Quindi, per impostazione predefinita, nulla è cambiato. Tuttavia, gli autori di strutture possono sovraccaricare getproperty
(non è possibile sovraccaricare getfield
) per fornire funzionalità extra alla sintassi punto:
julia> function Base.getproperty(a::A, v::Symbol)
if v == :c
return getfield(a, :c) * 2
elseif v == :q
return "q"
else
return getfield(a, v)
end
end
julia> a.q
"q"
julia> getfield(a, :q)
ERROR: type A has no field q
julia> a.c
6
julia> getfield(a, :c)
3
julia> a.b
"foo"
Quindi possiamo aggiungere funzionalità extra alla sintassi del punto (dinamicamente se vogliamo). Un esempio concreto in cui ciò è utile è per il pacchetto PyCall.jl in cui era necessario scrivere pyobject[:field]
mentre ora è possibile implementarlo in modo tale da poter scriverepyobject.field.
La differenza tra setfield!
e setproperty!
è analoga alla differenza tra getfield
e getproperty
, spiegata sopra.
Inoltre, è possibile collegarsi alla funzione Base.propertynames
per fornire il completamento con tabulazione delle proprietà nella REPL. Per impostazione predefinita, verranno visualizzati solo i nomi dei campi:
julia> a.<TAB><TAB>
b c
Ma sovraccaricandoci propertynames
possiamo fargli mostrare anche la proprietà extra q
:
julia> Base.propertynames(::A) = (:b, :c, :q)
julia> a.<TAB><TAB>
b c q