types - 在其他模块中使用 Julia 抽象类型

标签 types scope julia

我正在尝试在 Julia 中使用抽象类型,但遇到了一些我自己似乎无法解决的问题。

假设我在不同的文件中有 2 个 Julia 模块和一个脚本(或 REPL),它们看起来像这样:

------------------------------------- File 1

module Mod1
  export AbstractThing

  abstract type AbstractThing end

end

------------------------------------- File 2

module Mod2 
  export Thing
  
  include("path/to/File1")
  using Mod1
  
  struct Thing <: AbstractThing
    ...
  end

  function f1()
    v :: Vector{AbstractThing} = []
    push!(v,Thing())
  end
end

------------------------------------- File 3

  include("path/to/File1")
  using Mod1

  include("path/to/File2")
  using Mod2

  function f2()
    v :: Vector{AbstractThing} = []
    push!(v,Thing())
  end

  function f3()
    v :: Vector{Main.Mod2.Mod1.AbstractThing} = []
    push!(v,Thing())
  end

我希望 f2() 可以工作,但由于某些原因它没有。从 REPL 执行时,它返回以下错误:

ERROR: LoadError: MethodError: Cannot `convert` an object of type Thing to an object of type AbstractThing

它与范围有关,因为 f1()f3() 都可以工作,但我无法真正弄清楚哪里出了问题或我应该修复它。

有人可以解释类型范围在这种情况下如何工作以及如何修复它吗?为什么 Julia 将 Main.Mod2.Mod1.AbstractThingMain.Mod1.AbstractThing 视为不同的类型?我该如何解决这个问题?


更新:

经过更多测试,我认为问题在于 Julia 解释器无法识别 Mod1 和 Mod2.Mod1 实际上是同一个模块。以下是我从 REPL 获得的一些输出,它们让我这样想:

julia> AbstractThing === Mod1.AbstractThing
true

julia> AbstractThing === Mod2.Mod1.AbstractThing
false

julia> Thing <: Mod1.AbstractThing
false

julia> Thing <: Mod2.Mod1.AbstractThing
true

所以它肯定是在查看 AbstractThing 的两个定义并将它们视为不同的。我不知道如何解决这个问题,但恐怕重组我的文件不是一个选择。我希望不同的人能够根据随后在 Mod1 中识别的模板实现他们自己的 Thing 结构。

可以使 Mod1 成为一个实际的包(而不仅仅是一个本地模块)吗?

最佳答案

正如@pfitzseb 对您的评论,您需要重构代码以避免两次包含一个文件。 以下是一个有效的示例。另见我的 tutorial on packages or modules (也可通过 YouTube video 获得):

------------------------------------- file1.jl:
module Mod1
  export AbstractThing

  abstract type AbstractThing end

end
------------------------------------- file2.jl:
module Mod2 
  export Thing, f1
  using ..Mod1 # You need to "go up" one level to main and then "go down" one level to Mod1
  
  struct Thing <: AbstractThing
    
  end

  function f1()
    v :: Vector{AbstractThing} = []
    push!(v,Thing())
  end
end
------------------------------------- file3.jl:
include("file1.jl") # Do all the "includes" at the beginning of your project..
include("file2.jl")
using .Mod1 # Here you are in Main, you need to go down one level to Mod1..
using .Mod2 # Same here to Mod2

function f2()
  v :: Vector{AbstractThing} = []
  push!(v,Thing())
end

function f3()
  v :: Vector{Main.Mod2.Mod1.AbstractThing} = []
  push!(v,Thing())
end

f1()
f2()
f3()

关于types - 在其他模块中使用 Julia 抽象类型,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/70641210/

相关文章:

julia - 如何检查文件是否在 Julia 中无异常(exception)地存在?

c# - System.Drawing.Point 是一种值类型。为什么?

c++ - 在没有反射/内省(introspection)的情况下确定 C++ 中的类类型

Julia:在 Juno/Atom 中运行代码块

c# - C# 中的命名空间作用域

objective-c - 如何将 NSString 从一个 View Controller 传递到另一个 View Controller ?

随机 BigFloats Julia

typescript - TypeScript 中的类型化枚举实例

haskell - 使用 Haskell 的类型系统来强制模块化

javascript - 具有多个嵌套 IIFE 的函数作用域