在其他模块中使用 Julia 抽象类型
Using Julia abstract types in other modules
我正在尝试在 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 执行时,returns 出现以下错误:
ERROR: LoadError: MethodError: Cannot `convert` an object of type Thing to an object of type AbstractThing
它与范围有关,因为 f1()
和 f3()
都可以工作,但我无法真正弄清楚哪里出了问题或我应该如何解决它。
谁能解释一下类型作用域在这种情况下是如何工作的以及如何解决它?为什么 Julia 将 Main.Mod2.Mod1.AbstractThing
和 Main.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
成为一个实际的包(而不仅仅是一个本地模块)吗?
您必须导入 AbstractThing
才能扩展它。尝试添加一行
import Mod1.AbstractThing
在 Mod2
的定义中 using Mod1
行之后
正如@pfitzseb 对您的评论,您需要重构代码以避免两次包含一个文件。
以下是一个有效的示例。另见我的 tutorial on packages or modules (also available as 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()
我正在尝试在 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 执行时,returns 出现以下错误:
ERROR: LoadError: MethodError: Cannot `convert` an object of type Thing to an object of type AbstractThing
它与范围有关,因为 f1()
和 f3()
都可以工作,但我无法真正弄清楚哪里出了问题或我应该如何解决它。
谁能解释一下类型作用域在这种情况下是如何工作的以及如何解决它?为什么 Julia 将 Main.Mod2.Mod1.AbstractThing
和 Main.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
成为一个实际的包(而不仅仅是一个本地模块)吗?
您必须导入 AbstractThing
才能扩展它。尝试添加一行
import Mod1.AbstractThing
在 Mod2
using Mod1
行之后
正如@pfitzseb 对您的评论,您需要重构代码以避免两次包含一个文件。 以下是一个有效的示例。另见我的 tutorial on packages or modules (also available as 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()