Search code examples
oopfortranassignment-operator

Inherit assignment from parent class in Fortran


Sorry, me again!

Even though I'm getting better with OOP in Fortran (which is probably the craziest thing I've ever worked with), I have difficulties with inheritance. Unfortunately I do not understand the syntax which allows me to do that.

Basically, what I want to do is override the assignment operator = which allows me to return any primitive type. A basic example with only one primitive type (real) would look like this:

module overload

    implicit none

    public func, assignment(=)

    interface assignment(=)
        module procedure equalAssignmentReal
        !! additional procedures for integer, character, logical if neccessary
    end interface

contains

    subroutine equalAssignmentReal(lhs, rhs)      !! <-- all these subroutines should be in the parent class

        implicit none

        real,     intent(out) :: lhs
        class(*), intent(in)  :: rhs

        select type(rhs)
            type is (real)
                lhs = rhs
        end select

        return

    end subroutine equalAssignmentReal

    function func(string) result(res)      !! <-- I want this function in the child class

        implicit none

        character(len=*), intent(in) :: string
        class(*), allocatable        :: res

        if (  string == "real" ) allocate(res, source=1.0)

        return

    end function func

end module overload

program test

    use overload

    implicit none

    real :: var

    var = func('real')

    print *, "var = ", var

end program test

This works when compiling with GNU Fortran (not with Intel as they permit intrinsic assignment overloading). So my question is now how would I define a parent class in a separate module which contains all the assignment overloads (real, integer, character, logical) and use this overrides in a child class which only contains func? In the program I only want to include the child class and assign the value with something like:

type(child_class) :: child
real :: var

var = child%func('real')

Any help appreciated!


Solution

  • As no one seems to know the answer and I have no clue how to work it out with types I post this "workaround" here in case someone has the same problem. I simply put the assignment overload into a separate module and use the module wherever I need it. A simplified example looks like this:

    module overload
    
        implicit none
    
        public assignment(=)
    
        interface assignment(=)
            module procedure equalAssignmentReal
            module procedure equalAssignmentInteger
            !! additional procedures for character, logical if neccessary
        end interface
    
    contains
    
        subroutine equalAssignmentReal(lhs, rhs)
    
            implicit none
    
            real,     intent(out) :: lhs
            class(*), intent(in)  :: rhs
    
            select type(rhs)
                type is (real)
                    lhs = rhs
            end select
    
            return
    
        end subroutine equalAssignmentReal
    
        subroutine equalAssignmentInteger(lhs, rhs)
    
            implicit none
    
            integer,  intent(out) :: lhs
            class(*), intent(in)  :: rhs
    
            select type(rhs)
                type is (integer)
                    lhs = rhs
            end select
    
            return
    
        end subroutine equalAssignmentInteger
    
    end module overload
    
    
    module assignment
    
        implicit none
    
        public find
        public par1
    
        real    :: par1
        integer :: par2
    
    contains
    
        subroutine init
    
            use overload
    
            implicit none
    
    
            par1 = find('real')
            par2 = find('integer')        
    
            return
    
        end subroutine init
    
        function find(in) result(out)
    
            implicit none
    
            character(len=*), intent(in)  :: in
            class(*), allocatable         :: out
    
            if ( in == 'real' ) then
    
                allocate(out, source=1.)
    
            else if ( in == 'integer' ) then
    
                allocate(out, source=2)
    
            end if 
    
            return
    
        end function find
    
    end module assignment
    
    program test
    
        use assignment
    
        implicit none
    
        call init
    
        print *, "par1 = ", par1
        print *, "par2 = ", par2
    
    end program test
    

    I use this to extract parameters of unknown primitive type from a file (json).