I am trying to work with abstract types in Julia, and am encountering some problems which I can't seem to figure out on my own.
Let's say I have 2 Julia modules and a script (or REPL) in different files such that they look like so:
------------------------------------- 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
What I would like is for f2() to work, but for some reason it does not. When executed from the REPL, it returns the following error:
ERROR: LoadError: MethodError: Cannot `convert` an object of type Thing to an object of type AbstractThing
It has something to do with scope, because both f1() and f3() work, but I can't really figure out what is wrong or what I should do to fix it.
Can someone explain how type scope works in this sort of context and how to fix it? Why is Julia seeing Main.Mod2.Mod1.AbstractThing and Main.Mod1.AbstractThing as separate types? How can I fix this?
Update:
After some more testing, I think the problem is that the Julia interpreter does not recognise that Mod1 and Mod2.Mod1 are actually the same module. Here are some of the outputs I got from the REPL that make me think this:
julia> AbstractThing === Mod1.AbstractThing
true
julia> AbstractThing === Mod2.Mod1.AbstractThing
false
julia> Thing <: Mod1.AbstractThing
false
julia> Thing <: Mod2.Mod1.AbstractThing
true
So it is definitely looking at the two definitions of AbstractThing and considering them as different. How can this be solved I do not know, but restructuring my files is not an option I am afraid. I want different people to be able to implement their own Thing struct, based on a template that is then recognised in Mod1.
Could making Mod1 an actual package (and not simply a local module) work?