How to make an abstract type as a super type of composite types

Hi,

I would like to create an abstract type, which is a supertype of several composite types, which I coded in modules, so that a function just works for the composite types, which have this specific abstract type as supertype. Furthermore I would like to use the package Reexport for loading all modules in just one module.

module MyModuleA

mutable struct MyTypeA
  var1
  var2
  ....
end

end

module MyModuleB

mutable struct MyTypeB
  var1
  var2
  ....
end

end

module MyModuleC

mutable struct MyTypeC
  var1
  var2
  ....
end

end

And MyModuleD should reexport the module MyModuleA, MyModuleB and MyModuleC and the abstract type MyType D should be the super type of MyTypeA, MyTypeB and MyTypeC

module MyModuleD

using Reexport

abstract type MyType D end

@reexport using MyModuleA
@reexport using MyModuleB
@reexport using MyModuleC

function my_function(var::MyTypeD)
   ....
end

end

My Problem is now:
When I use MyModuleD in MyModuleA, MyModuleB or MyModuleC to get the definition of the abstract type MyTypeD, that I get a warning "Replacing module MyModuleA because of the reexport in MyModule D.

Does somebody know how I have to code this?

To make D the supertype, you need to do something like

mutable struct A <: D
# ...
end

But this means you need to have D defined prior to the definition of A. As far as I know, there’s now way to make something the subtype of something else after the fact.

In your case, this may mean importing D in modules A-C, so I’m not sure the module structure you want is possible. Then again, I never use nested modules like that, so take that with a hefty grain of salt.

Edit: given your edit, seems like you already knew this, ignore me :face_with_raised_eyebrow:

Ok, thanks. So it would be better to just include the code in one big module? My construction works, but it leads to annoying warnings. And I think this isn´t the Julian way to do it :wink:

Reexporting stuff does not seem to be needed here; moreover if you really need to load all modules at once all the time, maybe they should not be modules. Anyway, an easy way to handle this is to define the abstract type from module D first, then use it in the rest of the modules (A,B,C as @kevbonham mentioned ) and not re-export anything; Your actual code will be contain

using MyModuleA, MyModuleB, MyModuleC
using MyModuleD  # if the abstract type is needed
...

PS If you really need the namespace or a hierarchical structure of sorts, A,B,C could be submodules of D.

1 Like

I would probably define all types in MyModule D:

abstract type MyTypeD end

mutable struct MyTypeA <: MyTypeD
<more>
end

Then put the code that does the work on each type in separate modules that use MyModuleD.

Thanks for your replies. Most of the time I would like to use the modules separately, but there are some functions, which should work on each module. Furthermore it would be useful, but not necessary, when I use MyModuleD that I can also use the structs and methods of the modules A, B and C within the same hierarchical structure. So that I can use

my_struct_a = MyModuleA.MyStructA(var1,....)

with using MyModuleD or MyModuleA.

Could you define your abstract type and the sub-types in modules MyTypes.
Then modules A, B, C use MyTypes and D uses A, B, C and MyTypes?
I.e., separate out type definitions into their own module?

I would love to do this

the other way around

mutable struct MyTypeA 
<more>
end

abstract type MyTypeB <: MyTypeA end
abstract type MyTypeC <: MyTypeA end

but I cannot figure out how.

Did you mean to reverse the “inequalities” here:

abstract type MyTypeB >: MyTypeA end
abstract type MyTypeC >: MyTypeA end

In other words, are you trying to define a struct and “later” (in another module that may not be used in all calls to the struct) make it a subtype of something else? I don’t think this is possible.

My conjecture is that you are doing this so that dispatch can be written based on the abstract type? Then you should not use a type hierarchy but traits. BinaryTraits.jl is a nice implementation, but there are others.

1 Like