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

23

Julia a les fonctions setter setproperty!et setfield!et les fonctions getter getpropertyet getfieldqui 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)
Kristoffer Carlsson
la source

Réponses:

27

fieldssont simplement les "composants" d'une structure. La struct

struct A
   b
   c::Int
end

a les champs bet c. Un appel à getfieldrenvoie 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.butilisée pour "abaisser", c'est-à-dire être la même que pour l'écriture getfield(a, :b). Ce qui a changé maintenant, c'est que l' a.babaissement de getproperty(a, :b)la valeur 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 aviez l'habitude d'écrire pyobject[:field] alors qu'il est maintenant possible de l'implémenter de telle sorte que vous puissiez écrirepyobject.field.

La différence entre setfield!et setproperty!est analogue à la différence entre getfieldet getproperty, expliquée ci-dessus.

De plus, il est possible de se connecter à la fonction Base.propertynamespour 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, propertynamesnous pouvons également faire apparaître la propriété supplémentaire q:

julia> Base.propertynames(::A) = (:b, :c, :q)

julia> a.<TAB><TAB>
b c q
Kristoffer Carlsson
la source
Vous ne pouvez donc pas surcharger getfield?
Alfaizkhan
3
Non, getfieldc'est une fonction spéciale (intégrée). Essayer de le surcharger donnera l'erreur cannot add methods to a builtin function.
Kristoffer Carlsson
Peut-être ajouter ces informations à la réponse quelque part?
StefanKarpinski
2
La réponse dit déjà explicitement "(il n'est pas possible de surcharger getfield)" donc, dans un sens, il est déjà là.
Kristoffer Carlsson