Reputation: 59
I need a little help about using inheritance rules. My intention is to use one derived type array for storaging results of calculation but i want to use that array also for storaging components values from main and extended derived types. For example, this is my example code which I want to transform:
MODULE DERIVED_TYPES
IMPLICIT NONE
! FIRST DERIVED TYPE
TYPE, PUBLIC :: DT_AA
INTEGER, PRIVATE :: I_AA
CONTAINS
PROCEDURE, PUBLIC:: CALCULATE => CALC_DATA_I_AA
PROCEDURE, PUBLIC:: T_I_AA => TAKE_DATA_I_AA
END TYPE DT_AA
PRIVATE :: CALC_DATA_I_AA
PRIVATE :: TAKE_DATA_I_AA
! SECOND DERIVED TYPE
TYPE, EXTENDS( DT_AA ), PUBLIC :: DT_BB
INTEGER, PRIVATE :: I_BB
CONTAINS
PROCEDURE, PUBLIC:: CALCULATE => CALC_DATA_I_BB
PROCEDURE, PUBLIC:: T_I_BB => TAKE_DATA_I_BB
END TYPE DT_BB
PRIVATE :: CALC_DATA_I_BB
PRIVATE :: TAKE_DATA_I_BB
CONTAINS
! TYPE DT_AA PROCEDURES
SUBROUTINE CALC_DATA_I_AA( THIS, INDX )
CLASS( DT_AA ) :: THIS
INTEGER, INTENT( IN ) :: INDX
THIS%I_AA = 1 + INDX
END SUBROUTINE CALC_DATA_I_AA
FUNCTION TAKE_DATA_I_AA( THIS ) RESULT( VALUE_I_AA )
CLASS( DT_AA ) THIS
INTEGER :: VALUE_I_AA
VALUE_I_AA = THIS%I_AA
END FUNCTION TAKE_DATA_I_AA
! TYPE DT_BB PROCEDURES
SUBROUTINE CALC_DATA_I_BB( THIS, INDX )
CLASS( DT_BB ) :: THIS
INTEGER, INTENT( IN ) :: INDX
THIS%I_BB = THIS%I_AA + INDX
END SUBROUTINE CALC_DATA_I_BB
FUNCTION TAKE_DATA_I_BB( THIS ) RESULT( VALUE_I_BB )
CLASS( DT_BB ) THIS
INTEGER :: VALUE_I_BB
VALUE_I_BB = THIS%I_BB
END FUNCTION TAKE_DATA_I_BB
END MODULE DERIVED_TYPES
PROGRAM INHERITANCE_RULE
USE, NON_INTRINSIC :: DERIVED_TYPES
IMPLICIT NONE
INTEGER :: I
INTEGER, PARAMETER :: N_CALC = 3
CLASS( DT_AA ), POINTER :: P_INH
TYPE( DT_AA ), TARGET :: P_A_INH( N_CALC )
DO I = 1, N_CALC
P_INH => P_A_INH( I )
CALL P_INH%CALCULATE( I )
WRITE(*,*) P_INH%T_I_AA(), P_INH%T_I_BB()
END DO
END PROGRAM INHERITANCE_RULE
In this case I can not use pointer P_INH
and function for taking component I_BB
values which is not member of extended derived type because I got this compile error message:
't_i_bb' is not a member of the 'dt_aa' structure
Which kind of change is useful for this case?
My IDE is Code::Blocks 17.12 with Gfortran compiler. The version of compiler is: MinGW 6.3.0.
Upvotes: 0
Views: 742
Reputation: 2148
Fundamentally, the desired outcome is to call the calculate
routines associated with the base and derived type and access the take
routines associated with the base and derived type. This has to be done through the derived type as the base knows nothing about the types which extend it. One way to achieve this without modifying your types is:
type(dt_bb) :: b(n_calc)
do i = 1, n_calc
call b(i)%dt_aa%calculate(i)
call b(i)%calculate(i)
write(*,*) b(i)%t_i_aa(), b(i)%t_i_bb()
end do
The output of the above is:
2 3
3 5
4 7
The order of the calculate
calls should be chosen to match your use case.
Edit:
To expand on my comment, If you modify the definition of calc_data_i_bb
to:
subroutine calc_data_i_bb( this, indx )
class( dt_bb ) :: this
integer, intent( in ) :: indx
call this%dt_aa%calculate(indx)
this%i_bb = this%i_aa + indx
end subroutine calc_data_i_bb
Then you can simplify the driver loop:
type(dt_bb) :: b(n_calc)
do i = 1, n_calc
call b(i)%calculate(i)
write(*,*) b(i)%t_i_aa(), b(i)%t_i_bb()
end do
This may be a better option depending on the use case.
Upvotes: 2