【问题标题】:Define default method on abstract type in Julia在 Julia 中定义抽象类型的默认方法
【发布时间】:2021-10-30 20:07:08
【问题描述】:

如何在单独的模块中提供 Julia 中方法的默认实现?例如,如果抽象类型位于同一个模块中,我没有问题,这就像我预期的那样工作:

abstract type Foo end

howdy(x::Foo)::Union{String, Nothing} = nothing

struct Bar <: Foo end

function howdy(x::Bar)::Union{String, Nothing}
    "I'm a Bar!"
end

struct Baz <: Foo end

if abspath(PROGRAM_FILE) == @__FILE__
    bar = Bar()
    s = howdy(bar)
    if isa(s, String)
        println(s)
    end
    baz = Baz()
    t = howdy(baz)
    if isa(t, String)
        println(t)
    end
end

但是,一旦我将抽象类型放入它自己的模块中,它就不再起作用了:

src/qux.jl,我输入:

module qux

abstract type Foo end

howdy(x::Foo)::Union{String, Nothing} = nothing

export Foo, howdy
end # module

然后在reproduce.jl 我输入:

using qux

struct Bar <: Foo end

function howdy(x::Bar)::Union{String, Nothing}
    "I'm a Bar!"
end

struct Baz <: Foo end

if abspath(PROGRAM_FILE) == @__FILE__
    bar = Bar()
    s = howdy(bar)
    if isa(s, String)
        println(s)
    end
    baz = Baz()
    t = howdy(baz)
    if isa(t, String)
        println(t)
    end
end

然后我得到:

julia --project=. reproduce.jl
I'm a Bar!
ERROR: LoadError: MethodError: no method matching howdy(::Baz)
Closest candidates are:
  howdy(::Bar) at ~/qux/reproduce.jl:5
Stacktrace:
 [1] top-level scope
   @ ~/qux/reproduce.jl:18
in expression starting at ~/qux/reproduce.jl:11

【问题讨论】:

    标签: inheritance module julia


    【解决方案1】:

    Julia 手册中的here 解释了您的问题。

    问题是在您的代码中,您可以在此处看到:

    julia> module qux
    
           abstract type Foo end
    
           howdy(x::Foo)::Union{String, Nothing} = nothing
    
           export Foo, howdy
           end # module
    Main.qux
    
    julia> using .qux
    
    julia> struct Bar <: Foo end
    
    julia> function howdy(x::Bar)::Union{String, Nothing}
               "I'm a Bar!"
           end
    howdy (generic function with 1 method)
    
    julia> methods(howdy)
    # 1 method for generic function "howdy":
    [1] howdy(x::Bar) in Main at REPL[4]:1
    
    julia> methods(qux.howdy)
    # 1 method for generic function "howdy":
    [1] howdy(x::Foo) in Main.qux at REPL[1]:5
    

    您有两个不同的howdy 函数,每个函数都有一个方法。一个在qux 模块中定义,另一个在Main 模块中定义。

    您要做的是向qux 模块中定义的howdy 函数添加一个方法。我通常会通过使用模块名称限定导出的函数名称来做到这一点,因为这是一种明确的方式来表明你想要做什么:

    julia> module qux
    
           abstract type Foo end
    
           howdy(x::Foo)::Union{String, Nothing} = nothing
    
           export Foo, howdy
           end # module
    Main.qux
    
    julia> using .qux
    
    julia> struct Bar <: Foo end
    
    julia> function qux.howdy(x::Bar)::Union{String, Nothing}
               "I'm a Bar!"
           end
    
    julia> methods(qux)
    # 0 methods:
    
    julia> methods(howdy)
    # 2 methods for generic function "howdy":
    [1] howdy(x::Bar) in Main at REPL[4]:1
    [2] howdy(x::Foo) in Main.qux at REPL[1]:5
    

    如您所见,您现在有一个 howdy 函数,它有两种方法,所有方法都可以按照您的意愿工作。

    【讨论】:

      猜你喜欢
      • 2017-09-03
      • 2017-10-12
      • 1970-01-01
      • 2021-03-25
      • 2012-08-27
      • 1970-01-01
      • 2022-01-09
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多