fields
- это просто «компоненты» структуры. Структура
struct A
b
c::Int
end
имеет поля b
и c
. Вызов getfield
возвращает объект, связанный с полем:
julia> a = A("foo", 3)
A("foo", 3)
julia> getfield(a, :b)
"foo"
В ранних версиях Julia синтаксис a.b
использовался для «понижения», то есть совпадения с написанием getfield(a, :b)
. Что изменилось сейчас, так это то, что a.b
понижается до getproperty(a, :b)
со стандартным отступлением
getproperty(a::Type, v::Symbol) = getfield(a, v)
Так что по умолчанию ничего не изменилось. Однако авторы структур могут перегрузить getproperty
(перегрузить getfield
невозможно), чтобы обеспечить дополнительную функциональность для синтаксиса точек:
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"
Таким образом, мы можем добавить дополнительные функции в синтаксис точки. (динамически, если мы хотим). В качестве конкретного примера, где это полезно, можно привести пакет PyCall.jl, в котором вы должны были писать pyobject[:field]
, а теперь можно реализовать его так, что вы можете написать pyobject.field.
Разница междуsetfield!
и setproperty!
аналогичны разнице между getfield
и getproperty
, описанной выше.
Кроме того, можно подключиться к функции Base.propertynames
, чтобы обеспечить завершение свойств табуляциив REPL. По умолчанию будут отображаться только имена полей:
julia> a.<TAB><TAB>
b c
Но, перегрузив propertynames
, мы можем заставить его также показать дополнительное свойство q
:
julia> Base.propertynames(::A) = (:b, :c, :q)
julia> a.<TAB><TAB>
b c q