fields
são simplesmente os "componentes" de uma estrutura. A estrutura
struct A
b
c::Int
end
tem os campos b
e c
. Uma chamada para getfield
retorna 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.b
costumava "abaixar", ou seja, ser a mesma que escrever getfield(a, :b)
. O que mudou agora é que a.b
diminui 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 getfield
e 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
getfield
é uma função especial (embutida). Tentar sobrecarregar dará o errocannot add methods to a builtin function
.getfield
)" e, de certa forma, ela já está lá.