gpt4 book ai didi

constructor - 内部构造函数到底是什么?

转载 作者:行者123 更新时间:2023-12-03 09:12:30 24 4
gpt4 key购买 nike

TL; DR:

  • 内部构造函数的准确定义是什么?在Julia-v0.6 +中,是否应该说“可以用签名typename{...}(...)(请注意{}部分)调用的任何构造函数都是内部构造函数”?
  • 如下面的评论所述,仅外部构造函数实际上是explicit inner constructor吗?
  • 使用methods检查方法是否是内部/外部构造函数是否正确?
  • 由Julia自动定义的默认构造函数与由用户明确定义的相应构造函数之间有什么区别?

  • 顺便说一句,我知道如何使用以及何时使用内部构造函数。我知道什么是内部构造函数,直到 outer-only constructors进入并使水浑浊为止。 :(

    让我们回想一下 doc中的一些语句:

    1. Outer Constructor Methods

    A constructor is just like any other function in Julia in that its overall behavior is defined by the combined behavior of its methods.

    2. Inner Constructor Methods

    An inner constructor method is much like an outer constructor method, with two differences: 1. It is declared inside the block of a type declaration, rather than outside of it like normal methods. 2. It has access to a special locally existent function called new that creates objects of the block's type.

    3. Parametric Constructors

    Without any explicitly provided inner constructors, the declaration of the composite type Point{T<:Real} automatically provides an inner constructor, Point{T}, for each possible type T<:Real, that behaves just like non-parametric default inner constructors do. It also provides a single general outer Point constructor that takes pairs of real arguments, which must be of the same type.



    我发现 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」

    但是, outer-only constructors给构造函数的故事增加了另一条皱纹:
    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,类型声明块中的 outer constructor,它也调用 new。我想这里的目的只是为了防止Julia为我们定义默认的内外构造函数对,但是在这种情况下,文档中的第二条语句仍然适用吗?这使新用户感到困惑。

    Here,我阅读了另一种内部构造函数形式:
    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{...}(...)(请注意 {}部分)调用的任何构造函数都是内部构造函数”?

    最佳答案

    举例来说,假设您要定义一个代表偶数的类型:

    julia> struct Even
    e::Int
    end

    julia> Even(2)
    Even(2)

    到目前为止,还不错,但是您还希望构造函数拒绝奇数,并且到目前为止, Even(x)不会:
    julia> Even(3)
    Even(3)

    因此,您尝试将自己的构造函数编写为
    julia> Even(x) = iseven(x) ? Even(x) : throw(ArgumentError("x=$x is odd"))
    Even

    和...鼓卷,请...它不起作用:
    julia> Even(3)
    Even(3)

    为什么?让我们问一下 Julia 她刚刚叫什么:
    julia> @which Even(3)
    Even(e::Int64) in Main at REPL[1]:2

    这不是您定义的方法(请查看参数名称和类型),这是隐式提供的构造函数。也许我们应该重新定义?好吧,不要在家尝试:
    julia> Even(e::Int) = iseven(e) ? Even(e) : throw(ArgumentError("e=$e is odd"))
    Even
    julia> Even(2)
    ERROR: StackOverflowError:
    Stacktrace:
    [1] Even(::Int64) at ./REPL[11]:0
    [2] Even(::Int64) at ./REPL[11]:1 (repeats 65497 times)

    我们刚刚创建了一个无限循环:我们重新定义了 Even(e)以递归调用自身。现在,我们面临一个鸡与蛋的问题:我们想重新定义隐式构造函数,但是我们需要其他一些构造函数来调用已定义的函数。如我们所见,调用 Even(e)不是一个可行的选择。

    解决方案是定义一个内部构造函数:
    julia> workspace()

    julia> struct Even
    e::Int
    Even(e::Int) = iseven(e) ? new(e) : throw(ArgumentError("e=$e is odd"))
    end


    julia> Even(2)
    Even(2)

    julia> Even(3)
    ERROR: ArgumentError: e=3 is odd
    ..

    在内部构造函数内部,可以使用 new()语法调用原始的隐式构造函数。该语法不适用于外部构造函数。如果尝试使用它,则会收到错误消息:
    julia> Even() = new(2)
    Even

    julia> Even()
    ERROR: UndefVarError: new not defined
    ..

    关于constructor - 内部构造函数到底是什么?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45328831/

    24 4 0
    Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
    广告合作:1813099741@qq.com 6ren.com