尝试了解参数类型和new内部方法可用的函数。该手册指出“可用于创建该类型的新对象的内部构造函数的特殊函数”。请参阅此处有关new 的手册部分和此处有关内部构造函数方法的手册部分。
考虑一个设计用于计算 之和的内部方法x,其中x可以是向量或元组,并给出参数类型T。自然而然地希望 的元素类型x能够通过它们的 sum 继承s。我似乎不需要new这个,对吗?
struct M{T}
x::T
s
function M(x)
s = sum(x)
x,s
end
end
julia> M([1,2,3])
([1, 2, 3], 6)
julia> M([1.,2.,3.])
([1.0, 2.0, 3.0], 6.0)
julia> typeof(M([1.,2.,3.]))
Tuple{Vector{Float64}, Float64}
Run Code Online (Sandbox Code Playgroud)
编辑: 更正!我打算让内部构造函数的最后一行是M(x,s)......这仍然是一个有趣的问题,所以我不会纠正它。与有何M(x,s)不同new{typeof(x)}(x,s)?
我见过的一种用法new是与 结合使用typeof(),例如:
struct M{T}
x::T
s
function M(x)
s = sum(x)
new{typeof(x)}(x,s)
end
end
julia> M([1,2,3])
M{Vector{Int64}}([1, 2, 3], 6)
julia> M([1.,2.,3.])
M{Vector{Float64}}([1.0, 2.0, 3.0], 6.0)
Run Code Online (Sandbox Code Playgroud)
如果想限制s为与 相同的类型怎么办x?也就是说,例如,如果x是一个向量,那么s应该是一个向量(在这种情况下,是一个元素的向量)。我该怎么做呢?如果我用 替换内部构造函数的最后一行x, new{typeof(x)}(s),我会得到可以理解的错误:
MethodError: Cannot `convert` an object of type Int64 to an object of type Vector{Int64}
Run Code Online (Sandbox Code Playgroud)
规则如下:
如果您正在为类型编写外部构造函数M,则该构造函数应通过最终调用内部构造函数返回一个实例M,如下所示M(<args>):
如果您正在编写内部构造函数,这将覆盖默认的内部构造函数。M因此,您必须通过调用返回一个实例new(<args>)。
“特殊函数new”的存在是为了允许构造还没有构造函数的类型。观察以下示例:
julia> struct A
x::Int
function A(x)
A(x)
end
end
julia> A(4)
ERROR: StackOverflowError:
Stacktrace:
[1] A(::Int64) at ./REPL[3]:4 (repeats 79984 times)
Run Code Online (Sandbox Code Playgroud)
这是 的构造函数的循环定义A,会导致堆栈溢出。你无法自力更生,因此 Julia 提供了该new函数作为规避此问题的方法。
您应该为new函数提供的参数数量等于结构中的字段数量。请注意,该new函数将尝试转换其输入的类型以匹配结构体字段的声明类型:
julia> struct B
x::Float64
B(x) = new(x)
end
julia> B(5)
B(5.0)
julia> B('a')
B(97.0)
julia> B("a")
ERROR: MethodError: Cannot `convert` an object of type String to an object
of type Float64
Run Code Online (Sandbox Code Playgroud)
(上面的内部构造函数B与默认内部构造函数完全相同。)
定义参数类型时,new必须为函数提供与您的类型的参数数量相同的参数(并且顺序相同),类似于参数类型的默认内部构造函数。首先观察参数类型的默认内部构造函数是如何使用的:
julia> struct Foo{T}
x::T
end
julia> Foo{String}("a")
Foo{String}("a")
Run Code Online (Sandbox Code Playgroud)
现在,如果您正在为 编写内部构造函数Foo,而不是Foo{T}(x)在构造函数内部编写,您可以将 替换Foo为new,如下所示:new{T}(x)。
您可能需要typeof帮助定义构造函数,但通常不需要。这是定义M类型的一种方法:
struct M{I, T}
x::I
s::T
function M(x::I) where I
s = sum(x)
new{I, typeof(s)}(x, s)
end
end
Run Code Online (Sandbox Code Playgroud)
我typeof在这里使用的I是任何返回数字的可迭代类型:
julia> typeof(M(1:3))
M{UnitRange{Int64},Int64}
julia> g = (rand() for _ in 1:10)
Base.Generator{UnitRange{Int64},var"#5#6"}(var"#5#6"(), 1:10)
julia> typeof(M(g))
M{Base.Generator{UnitRange{Int64},var"#5#6"},Float64}
Run Code Online (Sandbox Code Playgroud)
请注意,当您在参数类型的内部构造函数中使用时,需要new为您的类型提供参数:
julia> struct C{T}
x::Int
C(x) = new(x)
end
ERROR: syntax: too few type parameters specified in "new{...}" around REPL[6]:1
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1278 次 |
| 最近记录: |