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