Dear Fortran community, in our Fortran OOP code, we take advantage of the factory-object to initialize the right object based on a string, coming from user input. We use a simple if-else construct in subroutine, like this
subroutine factory(concrete_type, typename)
class(base_t), intent(inout), allocatable :: concrete_type
character(len=*) :: typename
if (trim(typename) .eq. 'type1') then
allocate(type1_t::concrete_type)
else if (trim(typename) .eq. 'type2') then
allocate(type2_t::concrete_type)
end if
end subroutine
Dead simple and works as intended. But the obvious issue here is that whenever a new subtype of base_t
is added to the code, it should be manually added to the factory. Not a big deal, perhaps, but we envision that in the future people will write their own subcomponents to our code, which will add new subtypes. We will probably not want to integrate all of those centrally, so people would have to maintain their own fork, where they added the subtype to the factory.
An ideal alterantive would be something similar to the following Julia code, which was recently shared in a blog post.
module RegisterFruitFactory
abstract type Fruit end
const FRUIT_MAP = Dict{String, DataType}()
function register!(fruit::Type{<:Fruit}, name::String)
FRUIT_MAP[name] = fruit
end
function fruit(str::String)
fruit_type = get(FRUIT_MAP, str, nothing)
if isnothing(fruit_type)
error("Unknown fruit $str")
else
return fruit_type()
end
end
end
# Add type to the factory in a separate module
module RegisterFruitExtension
import ..RegisterFruitFactory
struct Banana <: RegisterFruitFactory.Fruit end
RegisterFruitFactory.register!(Banana, "banana")
end
So there is basically a map from string to type, which can be extended in submodules. I’ve been trying to wrap my head around whether this is possible to achieve in Frotran, and could not arrive to a solution.
Does anyone have an idea? Or maybe knows another way of creating an extendable factory.