我正在重新阅读Julia语言文档,以构建一个性能声音队列应用程序,而有关参数构造函数和外部构造函数的部分让我感到困惑。他们显示的示例如下:
julia> struct OurRational{T<:Integer} <: Real
num::T
den::T
function OurRational{T}(num::T, den::T) where T<:Integer
if num == 0 && den == 0
error("invalid rational: 0//0")
end
g = gcd(den, num)
num = div(num, g)
den = div(den, g)
new(num, den)
end
end
julia> OurRational(n::T, d::T) where {T<:Integer} = OurRational{T}(n,d)
OurRational
julia> OurRational(n::Integer, d::Integer) = OurRational(promote(n,d)...)
OurRational
julia> OurRational(n::Integer) = OurRational(n,one(n))
OurRational
文档说明:
第一个是“标准”通用(外部)构造函数,当它们具有相同的类型时,它们根据分子和分母的类型来推断类型参数T。
由此我了解到此构造函数处理两个参数的情况。它从(num和den)的类型推断T,然后将其提供给OurRational内部构造函数。
文档继续说:
当给定的分子和分母的值具有不同类型时,第二种方法适用:它将它们提升为公共类型,然后将构造委托给外部构造函数以匹配类型的参数。
看代码,我看不出这种情况。根据我认为Julia的评估方式,第二个构造函数是否不能处理n和d均为显式整数的情况?否则,我很难看到茱莉亚如何看待这一行。另外,赋值后缀中的省略号表示类似“现在当两个参数具有相同类型时转到外部构造函数”对吗?
我很了解第三个外部构造函数。
第一个和第二个外部构造函数不同,因为第二个外部构造函数处理分子和分母都是整数,但又是两个不同的具体子类型(都是抽象类型Integer)的情况。
Julia如您所知,具有许多内置的Integer类型。以UInt8为例,这是单字节语法的默认类型,例如0x1f。看一下结果我们混合使用UInt8和默认的Integer类型Int64:
julia> struct OurRational{T<:Integer} <: Real
num::T
den::T
function OurRational{T}(num::T, den::T) where T<:Integer
println("Inner")
if num == 0 && den == 0
error("invalid rational: 0//0")
end
g = gcd(den, num)
num = div(num, g)
den = div(den, g)
new(num, den)
end
end
julia>
julia> OurRational(n::T, d::T) where {T<:Integer} = begin println("Outer 1"); OurRational{T}(n,d) end
OurRational
julia> OurRational(n::Integer, d::Integer) = begin println("Outer 2"); OurRational(promote(n,d)...) end
OurRational
julia> OurRational(n::Integer) = begin println("Outer 3"); OurRational(n,one(n)) end
OurRational
julia> OurRational{UInt8}(0x2, 0x5)
Inner
OurRational{UInt8}(0x02, 0x05)
julia> OurRational(2, 5)
Outer 1
Inner
OurRational{Int64}(2, 5)
julia> OurRational(0x2, 5)
Outer 2
Outer 1
Inner
OurRational{Int64}(2, 5)
julia> OurRational(0x3)
Outer 3
Outer 1
Inner
OurRational{UInt8}(0x03, 0x01)
因此,第二个外部构造函数将参数提升为相同类型,然后将其移交给第一个外部构造函数,然后将其移交给内部构造函数。