- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
I need some help please.
In this code I create two objects (MM and FF) that extend an abstract
object (MF). Then I have a subroutine (execute_MM_or_FF) that is
supposed to handle both objects (MM and FF).
I tried several ways of doing it but none worked; this is an example
for which I get the error message
error #8169: The specified interface is not declared. [OUTPUT]
What is the problem with this code? thanks
!===================================
module Abstract_class_m
implicit none
private
type , abstract , public :: MF
contains
procedure (output_info) , deferred :: output
end type
abstract interface
subroutine output_info( me , iter)
import :: MF
class(MF) , intent(in) :: me
Integer , intent(in) :: iter
end subroutine
end interface
end module Abstract_class_m
!===================================
module MM_class_m
use Abstract_class_m
implicit none
private
public :: MM
type,extends(MF):: MM
integer :: ITMAX = 200
character (len=2) :: driver
contains
procedure :: output => output_MM
end type MM
interface MM
module procedure constructor
end interface
contains
function constructor( ) result( me )
implicit none
type(MM) :: me
me % driver = "MM"
end function constructor
!
!
subroutine output_MM( me , iter)
implicit none
class(MM) , intent(in) :: me
integer , intent(in) :: iter
print*, me%driver , iter
end subroutine output_MM
end module MM_class_m
!===================================
module FF_class_m
use Abstract_class_m
implicit none
private
public :: FF
type,extends(MF):: FF
integer :: ITMAX = 20
character (len=2) :: driver
contains
procedure :: output => output_FF
end type FF
interface FF
module procedure constructor
end interface
contains
function constructor( ) result( me )
implicit none
type(FF) :: me
me % driver = "FF"
end function constructor
!
!
subroutine output_FF( me , iter)
implicit none
class(FF) , intent(in) :: me
integer , intent(in) :: iter
print*, me%driver , iter
end subroutine output_FF
end module FF_class_m
!===================================
module execute_MM_or_FF
use MM_class_m , only: MM
use FF_class_m , only: FF
use Abstract_class_m , only: MF
implicit none
public :: execute
private
type, extends(MF) :: OBJ
integer :: ITMAX
character(len=2) :: driver
contains
procedure :: output
end type
contains
subroutine execute( me , n )
class(OBJ) , intent(inout) :: me
integer , intent(in) :: n
print*, me%itmax
call me%output(n)
end subroutine execute
end module execute_MM_or_FF
!===================================
program test
use MM_class_m , only: MM
use FF_class_m , only: FF
use execute_MM_or_FF , only: execute
implicit none
character(2) :: driver = "MM"
integer :: iter = 3
type(MM) :: a
type(FF) :: b
if(driver == "MM") then
a = MM()
call execute(a,iter)
else
b = FF()
call execute(b,iter)
end if
end program test
Link Copied
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
The error arises because the `OBJ` type in the `execute_MM_or_FF module` declares a binding called `output`. There is no procedure named `output` in that module to implement that binding. I'm not sure what your intent was here - if you wanted to override that binding in the OBJ type then you need to provide the procedure, if you just wanted the binding to continue to refer to the procedure that the binding references in the parent type, then you do not redeclare it in the extension.
I note that in your main program you are using a CALL statement to invoke `execute_MM_or_FF` - that is - you are trying to call a module. You cannot do that. The thing being invoked by a CALL statement needs to be a subroutine.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
My apologies, the CALL statement to invoke `execute_MM_or_FF´ was a mistake. It has been corrected in the example program.
Anyway, my intention is to call ´execute´ having either ´a´ or ´b´ as an argument, whereas the subroutine ´execute´ in module ´execute_MM_or_FF´ handles either objects through the class OBJ that has the same parent as MM and MF
I have tried to implement this code through various different constructions. I also understand that the procedure ´output´ of OBJ should be implemented, but I actually want to inherit ouput from either MM or FF depending on the type of argument ´me´ that is passed to ´execute´.
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Fortran does not support multiple inheritance, if that is what you are trying to do.
`execute` currently takes an object of type OBJ. It can't take an object of declared type MM or FF, they are not extensions of OBJ.
Your MM, FF and OBJ types all have the same components. Is it really necessary that they be separate types? Could you have another type, that was an extension of MF and that acted as the parent of the other types, that had those common components? If so, execute just takes an object of that type, and then just calls the output binding.
If not - you need to explain what you are trying to achieve.
module Abstract_class_m implicit none private type , abstract , public :: MF contains procedure (output_info) , deferred :: output end type abstract interface subroutine output_info( me , iter) import :: MF implicit none class(MF) , intent(in) :: me Integer , intent(in) :: iter end subroutine end interface type, extends(MF), abstract, public :: MF_intermediate integer :: ITMAX character (len=2) :: driver end type MF_intermediate end module Abstract_class_m module MM_class_m use Abstract_class_m implicit none private public :: MM type, extends(MF_intermediate) :: MM contains procedure :: output => output_MM end type MM interface MM module procedure constructor end interface contains function constructor( ) result( me ) type(MM) :: me me % ITMAX = 200 me % driver = "MM" end function constructor subroutine output_MM(me , iter) class(MM) , intent(in) :: me integer , intent(in) :: iter print*, me%driver , iter end subroutine output_MM end module MM_class_m module FF_class_m use Abstract_class_m implicit none private public :: FF type,extends(MF_intermediate):: FF contains procedure :: output => output_FF end type FF interface FF module procedure constructor end interface contains function constructor( ) result( me ) type(FF) :: me me % driver = "FF" me % ITMAX = 20 end function constructor subroutine output_FF(me , iter) class(FF) , intent(in) :: me integer , intent(in) :: iter print*, me%driver , iter end subroutine output_FF end module FF_class_m module execute_MM_or_FF use MM_class_m , only: MM use FF_class_m , only: FF use Abstract_class_m , only: MF_intermediate implicit none public :: execute private contains subroutine execute(me , n) class(MF_intermediate) , intent(inout) :: me integer , intent(in) :: n print*, me%itmax call me%output(n) end subroutine execute end module execute_MM_or_FF program test use FF_class_m , only: FF use MM_class_m , only: MM use execute_MM_or_FF character(2) :: driver = "MM" integer :: iter = 3 type(MM) :: a type(FF) :: b if(driver == "MM") then a = MM() call execute(a,iter) else b = FF() call execute(b,iter) end if end program test
- Mark as New
- Bookmark
- Subscribe
- Mute
- Subscribe to RSS Feed
- Permalink
- Report Inappropriate Content
Perhaps this is not multiple inheritance, but I finally managed a way to do what I want in the code below.
!=============================
module Parent_class_m
implicit none
private
type , public :: MF
integer :: ITMAX = 100
character (len=2) :: driver_abs
contains
procedure :: output
end type
contains
subroutine output( me , iter)
class(MF) , intent(in) :: me
Integer , intent(in) :: iter
end subroutine
end module Parent_class_m
!=============================
module MM_class_m
use Parent_class_m
implicit none
private
public :: MM
type,extends(MF):: MM
integer :: ITMAX_MM = 200
character (len=2) :: driver
contains
procedure :: output => output_MM
end type MM
interface MM
module procedure constructor
end interface
contains
function constructor( ) result( me )
implicit none
type(MM) :: me
me % itmax = me % itmax_MM
me % driver = "MM"
end function constructor
!
!
subroutine output_MM( me , iter)
implicit none
class(MM) , intent(in) :: me
integer , intent(in) :: iter
print*, me%driver , iter
end subroutine output_MM
end module MM_class_m
!=============================
module FF_class_m
use Parent_class_m
implicit none
private
public :: FF
type,extends(MF):: FF
integer :: ITMAX_FF = 20
character (len=2) :: driver
contains
procedure :: output => output_FF
end type FF
interface FF
module procedure constructor
end interface
contains
function constructor( ) result( me )
implicit none
type(FF) :: me
me % itmax = me%itmax_FF
me % driver = "FF"
end function constructor
!
!
subroutine output_FF( me , iter)
implicit none
class(FF) , intent(in) :: me
integer , intent(in) :: iter
print*, me%driver , iter+100
end subroutine output_FF
end module FF_class_m
!=============================
module execute_MM_or_FF
use MM_class_m , only: MM
use FF_class_m , only: FF
use Parent_class_m , only: MF
implicit none
public :: execute
private
contains
subroutine execute( me , n )
class(MF) , intent(inout) :: me
integer , intent(in) :: n
print*, me%itmax
call me%output(n)
end subroutine execute
end module execute_MM_or_FF
!=============================
program test
use MM_class_m , only: MM
use FF_class_m , only: FF
use execute_MM_or_FF , only: execute
implicit none
character(2) :: driver = "MM"
integer :: iter = 3
type(MM) :: a
type(FF) :: b
if(driver == "FF") then
a = MM()
call execute(a,iter)
else
b = FF()
call execute(b,iter)
end if
end program test
- Subscribe to RSS Feed
- Mark Topic as New
- Mark Topic as Read
- Float this Topic for Current User
- Bookmark
- Subscribe
- Printer Friendly Page