Should abstract types be exported?

My module has a few composite types like: struct myType1 <: ModFooAbstractType.
It seems the intent of abstract types is that they are an interface for functions, not necessarily defined in the same module, like:

using ModFoo

function bar(x::ModFooAbstractType)
   print("bar")
end

Are there any drawbacks to this?

Someone could explain better but:

  1. You can create new methods for functions in other module.
  2. You can create your own functions using concrete types of other modules.

Consequently, it seems to me that exporting abstract structs is only useful if:

  1. It is clear which are the functions that any new subtypes of your exported abstract types should implement.
  2. You wanna allow for the users to both:
    1. Create new subtypes of your abstract types that will work automatically with any generic/fallback functions you have written.
    2. Allow them to write generic/fallback functions for your abstract types, i.e., they can write functions that can be extended for specific concrete types, but already have a generic implementation that should work for any subtype of your abstract type anyway.
4 Likes

Not at all. This is what Julia was designed to do. It was meant to be extensible in this way.

I don’t disagree with @Henrique_Becker, but [your] response makes it sound like this pattern is to be avoided in all but a few restricted cases.

I think this feature is very powerful and might actually be useful (and more elegant) to solve more problems than most of us currently associate with this technique.

EDIT: There may indeed be drawbacks, but I don’t see any in your particular example.

1 Like

Meaning of export

As a sidenote: In Julia, the term “exported” means your ModFoo module runs:

export ModFooAbstractType

Which makes the symbol ModFooAbstractType directly available to any module that calls using ModFoo.

Should you export?

So if you are asking whether it is a good idea to export this symbol, it all depends on if the convenience of having that symbol directly available to your users instead of explicitly qualifying the new type. Here is an example of using an explicit ModFoo. qualifier:

using ModFoo

function bar(x::ModFoo.ModFooAbstractType)
   print("bar")
end

Note that, by not export-ing the symbol, you can rename ModFooAbstractType → SomeAbstractType without worrying about name collisions.

So really, your choice to export is a tradeoff between convenience for module users to write the type name without needing an explicit qualifier, and the inconvenience of potential name collisions.

1 Like