Qual'è la differenza tra campi e proprietà in Julia?


23

Julia ha le funzioni setter setproperty!e setfield!e le funzioni getter getpropertye getfieldche operano su strutture. Qual è la differenza tra proprietà e campi in Julia?

Ad esempio, quanto segue sembra indicare che fanno la stessa cosa:

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)

Risposte:


27

fieldssono semplicemente i "componenti" di una struttura. La struttura

struct A
   b
   c::Int
end

ha i campi be c. Una chiamata per getfieldrestituire l'oggetto associato al campo:

julia> a = A("foo", 3)
A("foo", 3)

julia> getfield(a, :b)
"foo"

Nelle prime versioni di Julia, la sintassi a.butilizzata per "abbassare", ovvero essere la stessa della scrittura getfield(a, :b). Ciò che è cambiato ora è che si a.briduce a getproperty(a, :b)con il fallback predefinito

getproperty(a::Type, v::Symbol) = getfield(a, v)

Quindi, per impostazione predefinita, nulla è cambiato. Tuttavia, gli autori di strutture possono sovraccaricare getproperty(non è possibile sovraccaricare getfield) per fornire funzionalità extra alla sintassi punto:

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"

Quindi possiamo aggiungere funzionalità extra alla sintassi del punto (dinamicamente se vogliamo). Un esempio concreto in cui ciò è utile è per il pacchetto PyCall.jl in cui era necessario scrivere pyobject[:field] mentre ora è possibile implementarlo in modo tale da poter scriverepyobject.field.

La differenza tra setfield!e setproperty!è analoga alla differenza tra getfielde getproperty, spiegata sopra.

Inoltre, è possibile collegarsi alla funzione Base.propertynamesper fornire il completamento con tabulazione delle proprietà nella REPL. Per impostazione predefinita, verranno visualizzati solo i nomi dei campi:

julia> a.<TAB><TAB>
b c

Ma sovraccaricandoci propertynamespossiamo fargli mostrare anche la proprietà extra q:

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

julia> a.<TAB><TAB>
b c q

Quindi non puoi sovraccaricare Getfield?
Alfaizkhan,

3
No, getfieldè una funzione speciale (integrata). Cercare di sovraccaricare darà l'errore cannot add methods to a builtin function.
Kristoffer Carlsson,

Forse aggiungi quelle informazioni alla risposta da qualche parte?
StefanKarpinski,

2
La risposta dice già esplicitamente "(non è possibile sovraccaricare getfield)", quindi, in un certo senso, è già lì.
Kristoffer Carlsson,
Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.