简而言之:
- 内部构造器的准确定义是什么?在Julia-v0.6+中,可以说“任何可以使用签名
typename{...}(...)
(注意{}
部分)调用的构造器都是内部构造器”吗? - 如下面评论所述,外部唯一构造器实际上是一个
显式内部构造器
吗? - 使用
methods
检查方法是否为内部/外部构造器是正确的吗? - Julia自动定义的默认构造器与用户明确定义的对应构造器之间有什么区别?
顺便说一句,我知道如何使用和何时使用内部构造器。我知道什么是内部构造器,直到仅外部构造器出现并使事情变得混乱。 :(
让我们回忆一下文档中的一些声明:
1. 外部构造器方法
构造器就像Julia中的任何其他函数一样,其整体行为由其方法的组合行为定义。
2. 内部构造器方法
内部构造器方法与外部构造器方法非常相似,有两点不同:1.它在类型声明块内部声明,而不是像普通方法那样在外部声明。2.它可以访问一个特殊的本地存在的函数
new
,该函数创建块的类型的对象。3. 参数化构造器
如果没有提供明确的内部构造器,则复合类型
Point{T<:Real}
的声明自动为每个可能的类型T<:Real
提供一个内部构造器Point{T}
,其行为就像非参数化默认内部构造器一样。它还提供了一个单独的一般外部Point构造器,该构造器接受一对实数参数,这些参数必须是相同的类型。
我发现内部构造器方法
无法直接通过methods
观察,即使methods(Foo{Int})
有效,它实际上也不是“像Julia中的任何其他函数一样”,常见的泛型函数不能以这种方式使用methods
。
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
嗯,一个类型声明块中的外部构造函数,并且它也调用了new。我想这里的目的只是为了防止Julia为我们定义默认的内部-外部构造函数对吧?但是文档中的第二条语句在这种情况下仍然成立吗?这对新用户来说很困惑。
在这里,我读到还有一种形式的内部构造函数:
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{...}(...)
(注意{}
部分)调用的构造函数都是内部构造函数”?
new
调用内部构造函数在结构体定义之外的能力。也许甚至可以覆盖某些特定类型参数的内部构造函数以添加额外的约束条件,这可能会很方便。 - Dan Getz