fields
son simplemente los "componentes" de una estructura. La estructura
struct A
b
c::Int
end
tiene los campos b
y c
. Una llamada a getfield
devuelve el objeto que está vinculado al campo:
julia> a = A("foo", 3)
A("foo", 3)
julia> getfield(a, :b)
"foo"
En las primeras versiones de Julia, la sintaxis a.b
solía "bajar", es decir, ser lo mismo que escribir getfield(a, :b)
. Lo que ha cambiado ahora es que se a.b
reduce a getproperty(a, :b)
la reserva predeterminada
getproperty(a::Type, v::Symbol) = getfield(a, v)
Entonces, por defecto, nada ha cambiado. Sin embargo, los autores de estructuras pueden sobrecargar getproperty
(no es posible sobrecargar getfield
) para proporcionar funcionalidad adicional a la sintaxis de puntos:
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"
Entonces podemos agregar funcionalidad adicional a la sintaxis de puntos (dinámicamente si lo deseamos). Como un ejemplo concreto donde esto es útil es para el paquete PyCall.jl donde solía tener que escribir, pyobject[:field]
mientras que ahora es posible implementarlo de manera que pueda escribirpyobject.field.
La diferencia entre setfield!
y setproperty!
es análoga a la diferencia entre getfield
y getproperty
, explicada anteriormente.
Además, es posible conectarse a la función Base.propertynames
para proporcionar la finalización de tabulación de propiedades en REPL. Por defecto, solo se mostrarán los nombres de los campos:
julia> a.<TAB><TAB>
b c
Pero al sobrecargar propertynames
podemos hacer que también muestre la propiedad adicional q
:
julia> Base.propertynames(::A) = (:b, :c, :q)
julia> a.<TAB><TAB>
b c q
getfield
es una función especial (incorporada). Intentar sobrecargarlo dará el errorcannot add methods to a builtin function
.getfield
)", por lo que, en cierto sentido, ya está allí.