Julia a les fonctions setter setproperty!
et setfield!
et les fonctions getter getproperty
et getfield
qui opèrent sur les structures. Quelle est la différence entre les propriétés et les champs dans Julia?
Par exemple, ce qui suit semble indiquer qu'ils font la même chose:
Julia> mutable struct S
a
end
Julia> s = S(2)
S(2)
Julia> getfield(s, :a)
2
Julia> getproperty(s, :a)
2
Julia> setfield!(s, :a, 3)
3
Julia> s
S(3)
Julia> setproperty!(s, :a, 4)
4
Julia> s
S(4)
fields
sont simplement les "composants" d'une structure. La struct
struct A
b
c::Int
end
a les champs b
et c
. Un appel à getfield
renvoie l'objet qui est lié au champ:
Julia> a = A("foo", 3)
A("foo", 3)
Julia> getfield(a, :b)
"foo"
Dans les premières versions de Julia, la syntaxe a.b
Était utilisée pour "baisser", c'est-à-dire être la même que pour écrire getfield(a, :b)
. Ce qui a changé maintenant, c'est que a.b
Passe à getproperty(a, :b)
avec le repli par défaut
getproperty(a::Type, v::Symbol) = getfield(a, v)
Donc par défaut, rien n'a changé. Cependant, les auteurs de structures peuvent surcharger getproperty
(il n'est pas possible de surcharger getfield
) pour fournir des fonctionnalités supplémentaires à la syntaxe à points:
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"
Nous pouvons donc ajouter des fonctionnalités supplémentaires à la syntaxe des points (dynamiquement si nous voulons). Un exemple concret où cela est utile est pour le package PyCall.jl où vous deviez écrire pyobject[:field]
Alors qu'il est maintenant possible de l'implémenter de telle sorte que vous puissiez écrire pyobject.field.
La différence entre setfield!
Et setproperty!
Est analogue à la différence entre getfield
et getproperty
, expliquée ci-dessus.
De plus, il est possible de se connecter à la fonction Base.propertynames
Pour fournir une tabulation des propriétés dans le REPL. Par défaut, seuls les noms de champs seront affichés:
Julia> a.<TAB><TAB>
b c
Mais en surchargeant propertynames
, nous pouvons aussi lui faire afficher la propriété supplémentaire q
:
Julia> Base.propertynames(::A) = (:b, :c, :q)
Julia> a.<TAB><TAB>
b c q