Community
cancel
Showing results for 
Search instead for 
Did you mean: 
Highlighted
Beginner

The INTERFACE/CONTAINS stack is full, Superclass and Subclass pointing to each other

Jump to solution

Hey 

I have a circular dependencie. Is there any way to solve this in fortran?

MODULE mElement
	USE mProject
	IMPLICIT NONE
	
	PRIVATE
	PUBLIC :: tElement
	
	TYPE :: tElement
		INTEGER(4) :: element_property = 1234
		TYPE(tProject), POINTER	:: project
	CONTAINS
		PROCEDURE, PUBLIC ::  routine_using_project_data	=>  routine_using_project_data
	END TYPE tElement
CONTAINS
	SUBROUTINE routine_using_project_data(this)
		IMPLICIT NONE
		
		CLASS(tElement)	:: this
		REAL(8)			:: project_property(10)
		
		project_property = this%project%project_property
	END SUBROUTINE routine_using_project_data
END MODULE mElement

	
MODULE mProject
	USE mElement
	
	TYPE :: tProject
		TYPE(tElement), ALLOCATABLE   :: elements(:)
		REAL(8)						:: project_property(10)
	END TYPE tProject
	
END MODULE mProject
	
	
PROGRAM TEST
	USE mElement
	USE mProject
	IMPLICIT NONE

	TYPE(tProject) :: project
        CALL project%elements(1)%routine_using_project_data()
END PROGRAM TEST

I have Superclass which is containing Subclass Objects. The Subclass should point back to its Superclass

0 Kudos

Accepted Solutions
Highlighted
Valued Contributor II

Ian is right - I misread the

Jump to solution

Ian is right - I misread the error message I got with an adjusted version of the program.

Here is the version that is accepted (it does not do anything useful of course :)):

        MODULE mElement
            IMPLICIT NONE

            PRIVATE
            PUBLIC :: tElement, tProject

            TYPE :: tElement
                INTEGER(4) :: element_property = 1234
                TYPE(tProject), POINTER :: project
            END TYPE tElement

            TYPE :: tProject
                TYPE(tElement), ALLOCATABLE :: elements(:)
            END TYPE tProject

        END MODULE mElement

        PROGRAM TEST
            USE mElement
            IMPLICIT NONE
            TYPE(tProject) :: project
        END PROGRAM TEST

 

View solution in original post

0 Kudos
7 Replies
Highlighted
Valued Contributor II

I thought the problem could

Jump to solution

I thought the problem could be solved by merging the two modules, but no, you have a sort of forward use of tProject - it is not yet defined when you use it.

Solutions might be:

  • Define a dummy type of which you let tProject be an extension
  • Avoid the circularity altogether. As I am not sure what you are trying to achieve, that may or may not be simple

Fortran does allow types to be defined recursively, but that is no solution here.

 

0 Kudos
Highlighted
Black Belt

If the types were in the same

Jump to solution

If the types were in the same module, then the forward reference is fine.  What I think Arjen is referring to by recursive definition is just a specific case of the general rule - you can forward reference a type that is defined in the same scope in a pointer or allocatable component.
 

0 Kudos
Highlighted
Valued Contributor II
1 View

Ian is right - I misread the

Jump to solution

Ian is right - I misread the error message I got with an adjusted version of the program.

Here is the version that is accepted (it does not do anything useful of course :)):

        MODULE mElement
            IMPLICIT NONE

            PRIVATE
            PUBLIC :: tElement, tProject

            TYPE :: tElement
                INTEGER(4) :: element_property = 1234
                TYPE(tProject), POINTER :: project
            END TYPE tElement

            TYPE :: tProject
                TYPE(tElement), ALLOCATABLE :: elements(:)
            END TYPE tProject

        END MODULE mElement

        PROGRAM TEST
            USE mElement
            IMPLICIT NONE
            TYPE(tProject) :: project
        END PROGRAM TEST

 

View solution in original post

0 Kudos
Highlighted
Beginner

Quote:Arjen Markus wrote:

Jump to solution

Arjen Markus wrote:

Ian is right - I misread the error message I got with an adjusted version of the program.

Here is the version that is accepted (it does not do anything useful of course :)):

        MODULE mElement
            IMPLICIT NONE

            PRIVATE
            PUBLIC :: tElement, tProject

            TYPE :: tElement
                INTEGER(4) :: element_property = 1234
                TYPE(tProject), POINTER :: project
            END TYPE tElement

            TYPE :: tProject
                TYPE(tElement), ALLOCATABLE :: elements(:)
            END TYPE tProject

        END MODULE mElement

        PROGRAM TEST
            USE mElement
            IMPLICIT NONE
            TYPE(tProject) :: project
        END PROGRAM TEST

 

Thanks a lot. I will add some usefull routines :)

0 Kudos
Highlighted
Beginner

Unfortunately I have to

Jump to solution

Unfortunately I have to combine now a lot of different module and type in one big module with several thousand lines, which is not that handy. I discovered that I can also use submodules. This article from Dr. Fortran explains the basics and also this articel. But they do not explain how to handle type bounded subroutine and functions in submodules or how I can go around the circumference problem. How can I  use tElement in tProject If I am not allowed in mElement to declare tElement public? Visa versa it is working. tElement is allowed to have a pointer to tProject. 

mElement.f90

SUBMODULE (mProject) mElement
	TYPE :: tElement
		INTEGER(4)				:: element_property = 1234
		TYPE(tProject), POINTER	:: project
	CONTAINS
		PROCEDURE :: test1 => test_element
	END TYPE tElement
	
CONTAINS
	MODULE SUBROUTINE routine_using_project_data(elements_property)
		IMPLICIT NONE
		
		REAL(8), INTENT(IN)		:: elements_property
		REAL(8)					:: project_property
		
		project_property = elements_property
	END SUBROUTINE routine_using_project_data
	
	
	SUBROUTINE test_element(this)
		IMPLICIT NONE
		
		CLASS(tElement)		:: this
	
	END SUBROUTINE test_element
END SUBMODULE mElement

 

 

Test.f90

MODULE mProject
	IMPLICIT NONE
	
	PRIVATE
	! TYPES
	PUBLIC :: tProject
	
	! SUBROUTINES
	PUBLIC :: routine_using_project_data
	
	INTERFACE
		MODULE SUBROUTINE routine_using_project_data(elements_property)
			REAL(8), INTENT(IN)	:: elements_property
		END SUBROUTINE
	END INTERFACE
	
	TYPE :: tProject
		REAL(8)						:: project_property(10) = 10
	END TYPE tProject
	
CONTAINS
	
END MODULE mProject

	
PROGRAM TEST
	USE mProject
	IMPLICIT NONE
	
	TYPE(tProject), TARGET	:: project
	
	REAL(8)					:: elements_property
	
	elements_property = 5
	CALL routine_using_project_data(elements_property)
END PROGRAM TEST

 

0 Kudos
Highlighted
Black Belt

Put the type definitions in

Jump to solution

Put the type definitions in the scope of the module along with procedure interface definitions, put the procedure bodies in submodules.

MODULE mProject
  IMPLICIT NONE
  PRIVATE
  ! TYPES
  PUBLIC :: tProject
  ! SUBROUTINES
  PUBLIC :: routine_using_project_data
  
  INTEGER, PARAMETER, PUBLIC :: rk = KIND(1.0D0)
  INTEGER, PARAMETER :: ik = KIND(1)
  
  TYPE :: tProject
    REAL(rk) :: project_property(10) = 10
  END TYPE tProject
  
  TYPE :: tElement
    INTEGER(ik) :: element_property = 1234
    TYPE(tProject), POINTER	:: project
  CONTAINS
    PROCEDURE :: test1 => test_element
  END TYPE tElement
  
  INTERFACE
    MODULE SUBROUTINE routine_using_project_data(elements_property)
      IMPLICIT NONE
      REAL(rk), INTENT(IN)	:: elements_property
    END SUBROUTINE
    
    MODULE SUBROUTINE test_element(this)
      IMPLICIT NONE
      CLASS(tElement)		:: this
    END SUBROUTINE test_element
	END INTERFACE
END MODULE mProject


SUBMODULE (mProject) mElement
  IMPLICIT NONE
CONTAINS
  MODULE SUBROUTINE routine_using_project_data(elements_property)
    REAL(rk), INTENT(IN) :: elements_property
    REAL(rk) :: project_property
    
    project_property = elements_property
  END SUBROUTINE routine_using_project_data
  
  MODULE SUBROUTINE test_element(this)
    CLASS(tElement)		:: this
  END SUBROUTINE test_element
END SUBMODULE mElement


PROGRAM TEST
  USE mProject
  IMPLICIT NONE
  TYPE(tProject), TARGET	:: project
  REAL(rk)					:: elements_property
  
  elements_property = 5
  CALL routine_using_project_data(elements_property)
END PROGRAM TEST

 

0 Kudos
Highlighted
Beginner

perfect thanks a lot. Thats

Jump to solution

perfect thanks a lot. Thats exactly what I need.

0 Kudos