TL; DR:
- какое точное определение внутренних конструкторов? В Julia-v0.6 +, правильно ли сказать "любой конструктор, который можно вызывать с сигнатурой
typename{...}(...)
(обратите внимание на часть{}
), является внутренним конструктором"? - Как обсуждалось в комментарии ниже, конструктор только для внешнего интерфейса фактически
explicit inner constructor
? - Можно ли использовать
methods
для проверки того, является ли метод внутренним/внешним конструктором? - Какая разница между конструкторами по умолчанию, которые автоматически определяются Julia и соответствующими, явно определенными пользователями?
Кстати, я знаю, как использовать и когда использовать внутренний конструктор. Я знал, что такое внутренний конструктор, до тех пор, пока внешние конструкторы не войдут и не замутнут воды.:(
Вспомним некоторые утверждения из doc:
1. Методы внешнего конструктора
Конструктор аналогичен любой другой функции в Julia, поскольку его общее поведение определяется комбинированным поведением его методов.
2. Внутренние конструкторские методы
Метод внутреннего конструктора очень похож на метод внешнего конструктора с двумя отличиями: 1. Он объявляется внутри блока объявления типа, а не вне его, как обычные методы. 2. Он имеет доступ к специальной локально существующей функции под названием
new
, которая создает объекты типа блока.3. Параметрические конструкторы
Без каких-либо явно предоставляемых внутренних конструкторов объявление составного типа
Point{T<:Real}
автоматически предоставляет внутренний конструкторPoint{T}
для каждого возможного типаT<:Real
, который ведет себя так же, как и непараметрические внутренние конструкторы по умолчанию. Он также предоставляет один общий внешний конструктор Point, который принимает пары реальных аргументов, которые должны быть одного типа.
Я обнаружил, что inner constructor methods
не может быть непосредственно наблюдаемым methods
, даже methods(Foo{Int})
работает, он фактически не "точно так же, как любая другая функция", общие общие функции не могут быть methods
ed таким образом.
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」
Тем не менее, внешние конструкторы добавляет еще одну морщину в историю конструктора:
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, a outer constructor
В блоке объявления типа, и он также вызывает new
. Я предполагаю, что цель здесь состоит в том, чтобы не допустить, чтобы Джулия определяла для меня внутреннюю конструкторскую пару по умолчанию, но является ли второе утверждение из документации по-прежнему истинным в этом случае? Это запутывает новых пользователей.
Здесь, я прочитал другую форму внутренних конструкторов:
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
Это далеко от канонической формы Foo{T}(x::T) where {T} = new(x)
, но, похоже, результаты совершенно одинаковы.
Итак, мой вопрос - точное определение внутренних конструкторов? В Julia-v0.6 +, правильно ли сказать "любой конструктор, который можно вызывать с сигнатурой typename{...}(...)
(обратите внимание на часть {}
), является внутренним конструктором"?