fieldssão simplesmente os "componentes" de uma estrutura. A estrutura
struct A
b
c::Int
end
tem os campos be c. Uma chamada para getfieldretorna o objeto que está vinculado ao campo:
julia> a = A("foo", 3)
A("foo", 3)
julia> getfield(a, :b)
"foo"
Nas versões anteriores de Julia, a sintaxe a.bcostumava "abaixar", ou seja, ser a mesma que escrever getfield(a, :b). O que mudou agora é que a.bdiminui para getproperty(a, :b)o fallback padrão
getproperty(a::Type, v::Symbol) = getfield(a, v)
Então, por padrão, nada mudou. No entanto, os autores de estruturas podem sobrecarregar getproperty(não é possível sobrecarregar getfield) para fornecer funcionalidade extra à sintaxe de pontos:
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"
Portanto, podemos adicionar funcionalidades extras à sintaxe do ponto (dinamicamente, se quisermos). Como exemplo concreto, onde isso é útil, é para o pacote PyCall.jl, onde você costumava escrever, pyobject[:field] enquanto agora é possível implementá-lo de forma que você possa escreverpyobject.field.
A diferença entre setfield! e setproperty!é análoga à diferença entre getfielde getproperty, explicada acima.
Além disso, é possível conectar-se à função Base.propertynames para fornecer a conclusão de tabulação de propriedades no REPL. Por padrão, apenas os nomes dos campos serão mostrados:
julia> a.<TAB><TAB>
b c
Mas, sobrecarregando propertynames, podemos mostrar também a propriedade extra q:
julia> Base.propertynames(::A) = (:b, :c, :q)
julia> a.<TAB><TAB>
b c q