fields
są po prostu „komponentami” struktury. Struktura
struct A
b
c::Int
end
ma pola b
i c
. Wywołanie getfield
zwracające obiekt związany z polem:
julia> a = A("foo", 3)
A("foo", 3)
julia> getfield(a, :b)
"foo"
We wczesnych wersjach Julii składnia a.b
używana była do „obniżania”, tj. Bycia takim samym jak pisanie getfield(a, :b)
. To, co się teraz zmieniło, to a.b
obniżenie do getproperty(a, :b)
domyślnego stanu rezerwowego
getproperty(a::Type, v::Symbol) = getfield(a, v)
Domyślnie nic się nie zmieniło. Jednak autorzy struktur mogą przeciążać getproperty
(nie można przeciążać getfield
), aby zapewnić dodatkową funkcjonalność składni kropek:
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"
Możemy więc dodać dodatkową funkcjonalność do składni kropek (dynamicznie, jeśli chcemy). Konkretnym przykładem, w którym jest to przydatne, jest pakiet PyCall.jl, w którym kiedyś musiałeś pisać pyobject[:field]
, ale teraz możesz go zaimplementować tak, abyś mógł pisaćpyobject.field.
Różnica między setfield!
i setproperty!
jest analogiczna do różnicy między getfield
i getproperty
, wyjaśnionej powyżej.
Ponadto możliwe jest podpięcie się do funkcji w Base.propertynames
celu zapewnienia uzupełnienia tabulacji właściwościami w REPL. Domyślnie wyświetlane są tylko nazwy pól:
julia> a.<TAB><TAB>
b c
Ale przez przeciążenie propertynames
możemy sprawić, że pokaże także dodatkową właściwość q
:
julia> Base.propertynames(::A) = (:b, :c, :q)
julia> a.<TAB><TAB>
b c q
getfield
jest specjalną (wbudowaną) funkcją. Próba przeciążenia spowoduje błądcannot add methods to a builtin function
.getfield
)”, więc w pewnym sensie już tam jest.