# GameObj.jl
module GameObj
export GameObject
abstract type GameObject end
end
# WeaponObj.jl
module WeaponObj
export Weapon
include("GameObj.jl")
using .GameObj
abstract type Weapon <: GameObject end
end
# ChargeGunObj.jl
module ChargeGunObj
export ChargeGun
include("WeaponObj.jl")
using .WeaponObj
struct ChargeGun <: Weapon
number_of_charges::Int32
damage::Int32
function ChargeGun()
number_of_charges = 10
damage = 5
new(number_of_charges,damage)
end
end
end
using .ChargeGunObj
using .WeaponObj
function main()
cg :: Weapon = ChargeGun()
println(cg.damage)
end
main()
The problem is when I use Weapon
as a type annotation, it returns:
LoadError: MethodError: Cannot `convert` an object of type ChargeGun
to an object of type Weapon
and isa()
returns the incorrect result:
cg = ChargeGun()
println(isa(cg,Weapon)) # returns false, despite the fact that ChargeGun is a Weapon.
If I were to remove the modules and write everything out in the main.jl,
it works.
The problem is that you accidentally define two different modules named WeaponObj
. One is Main.WeaponObj
, and one is Main.ChargeGunObj.WeaponObj
. Your codes give something like this tree:
Main
├── ChargeGunObj
│ ├── ChargeGun <: Main.ChargeGunObj.WeaponObj.Weapon
│ └── WeaponObj
│ └── Weapon
└── WeaponObj
└── Weapon
where, in your main
function create a Main.ChargeGunObj.ChargeGun
(which is a subtype of Main.ChargeGunObj.WeaponObj.Weapon
but check if it is a subtype of Main.WeaponObj.Weapon
. (which, while they have the same name, are not the same type, i.e. Main.ChargeGunObj.WeaponObj.Weapon
!== Main.WeaponObj.Weapon
).
The rule is to only include
the same file once.
I’m a little confused about how to fix it, do I remove the using .WeaponObj
and just leave using .ChargeGun
?
If I do that, isa()
still returns false
, and I can’t do cg :: Weapon = ChargeGun()
because WeaponObj
isn’t available.
How about something like this:
$ cat GameObj.jl
module GameObj
export GameObject
abstract type GameObject end
end # module
$ cat WeaponObj.jl
module WeaponObj
export Weapon
# Use .. to look for GameObj in the parent module
# instead of including the file
using ..GameObj
abstract type Weapon <: GameObject end
end
$ cat ChargeGunObj.jl
module ChargeGunObj
export ChargeGun
using ..WeaponObj
struct ChargeGun <: Weapon
number_of_charges::Int32
damage::Int32
function ChargeGun()
number_of_charges = 10
damage = 5
new(number_of_charges, damage)
end
end
end
$ cat Game.jl
include("GameObj.jl")
include("WeaponObj.jl")
include("ChargeGunObj.jl")
using .GameObj, .WeaponObj, .ChargeGunObj
function main()
cg :: Weapon = ChargeGun()
println(cg.damage)
end
main()
$ julia Game.jl
5