web-dev-qa-db-fra.com

Quelle est la différence entre les champs et les propriétés dans Julia?

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)
23

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
27