TL;DR :
- quelle est la définition exacte des constructeurs internes ? Dans Julia-v0.6+, est-il correct de dire "tout constructeur qui peut être appelé avec la signature
typename{...}(...)
(notez le{}
partie) est un constructeur interne" ? - Comme discuté dans le commentaire ci-dessous, est-ce que le constructeur externe seulement est en fait une
explicit inner constructor
? - Est-il juste d'utiliser
methods
pour vérifier si une méthode est un constructeur interne/externe ? - Quelle est la différence entre les constructeurs par défaut qui sont définis automatiquement par Julia et les constructeurs correspondants définis explicitement par les utilisateurs ?
BTW, je sais comment utiliser et quand utiliser un constructeur interne. Je savais ce qu'était un constructeur interne jusqu'à ce que le programme Constructeurs externes uniquement est arrivé et a brouillé les pistes. :(
Rappelons quelques déclarations de la doc :
1. Méthodes du constructeur externe
Un constructeur est juste comme n'importe quelle autre fonction dans Julia dans la mesure où son comportement global est défini par le comportement combiné de ses méthodes.
2. Méthodes du constructeur interne
Une méthode de constructeur interne ressemble beaucoup à une méthode de constructeur externe, à deux différences près : 1. Elle est déclarée à l'intérieur du bloc de la déclaration de type, plutôt qu'à l'extérieur de celui-ci comme les méthodes normales. 2. Elle a accès à une fonction spéciale existant localement appelée
new
qui crée des objets du type du bloc.3. Constructeurs paramétriques
Sans aucun constructeur interne explicitement fourni, la déclaration du type composite
Point{T<:Real}
fournit automatiquement un constructeur interne,Point{T}
pour chaque type possibleT<:Real
qui se comporte exactement comme les constructeurs internes par défaut non paramétriques. Il fournit également un seul constructeur externe général Point qui prend des paires d'arguments réels, qui doivent être du même type.
J'ai trouvé inner constructor methods
ne peut pas être observé directement par methods
même methods(Foo{Int})
fonctionne, ce n'est en fait pas "comme n'importe quelle autre fonction", les fonctions génériques communes ne peuvent pas être methods
de cette façon.
julia> struct Foo{T}
x::T
end
julia> methods(Foo)
# 2 methods for generic function "(::Type)":
(::Type{Foo})(x::T) where T in Main at REPL[1]:2 # outer ctor 「1」
(::Type{T})(arg) where T in Base at sysimg.jl:24 # default convertion method「2」
julia> @which Foo{Int}(1) # or methods(Foo{Int})
(::Type{Foo{T}})(x) where T in Main at REPL[1]:2 # inner ctor 「3」
Cependant, le Constructeurs externes uniquement ajoute un autre aspect à l'histoire des constructeurs :
julia> struct SummedArray{T<:Number,S<:Number}
data::Vector{T}
sum::S
function SummedArray(a::Vector{T}) where T
S = widen(T)
new{T,S}(a, sum(S, a))
end
end
julia> methods(SummedArray)
# 2 methods for generic function "(::Type)":
(::Type{SummedArray})(a::Array{T,1}) where T in Main at REPL[1]:5 # outer ctor「4」
(::Type{T})(arg) where T in Base at sysimg.jl:24
Hmmm, un outer constructor
DANS un bloc de déclaration de type, et il appelle new
également. Je suppose que le but ici est juste d'empêcher Julia de définir la paire de constructeurs inner-outer par défaut pour nous, mais la deuxième déclaration de la documentation est-elle toujours vraie dans ce cas ? C'est déroutant pour les nouveaux utilisateurs.
Ici j'ai lu une autre forme de constructeurs internes :
julia> struct Foo{T}
x::T
(::Type{Foo{T}})(x::T) = new{T}(x)
end
julia> methods(Foo)
# 1 method for generic function "(::Type)":
(::Type{T})(arg) where T in Base at sysimg.jl:24
julia> methods(Foo{Int})
# 2 methods for generic function "(::Type)":
(::Type{Foo{T}})(x::T) where T in Main at REPL[2]:3 「5」
(::Type{T})(arg) where T in Base at sysimg.jl:24
C'est loin de la forme canonique Foo{T}(x::T) where {T} = new(x)
mais il semble que les résultats soient tout à fait les mêmes.
Ma question est donc la suivante : quelle est la définition exacte des constructeurs internes ? Dans Julia-v0.6+, est-il correct de dire "tout constructeur qui peut être appelé avec la signature typename{...}(...)
(notez le {}
partie) est un constructeur interne" ?