问题
I'm writing a module that access images and reads pixel values. The values in the images are usually of different data types (integer(2)
, integer(4)
, ...). Up to now, type image
is defined in the following way:
type, public :: image
logical :: initialized = .false.
character(256) :: path = "" ! Path to image
integer :: dimensions(3) = -1 ! Dimensions of image
integer :: datatype = 0 ! Datatype
contains
procedure :: initialize
procedure :: pxvalues
procedure :: getMeta
end type image
My question now: Is there a possibility that the program automatically finds the corresponding procedures depending on the data type of the image (stored in variable image%datatype
)? E.g. if the data type is integer, the subroutine pxvalues_integer
is called during the execution of image%pxvalues
.
Thanks!
回答1:
If you are unwilling to change the structure of your code, then the SELECT CASE approach proposed by bdforbes is an option.
Beyond that you may be able to use polymorphism and replace the datatype component by different types that are all extensions of the same parent type. This is the fundamental reason why type bound procedures (the procedure statements after the contains in the type definition) exist, so you might as well use them as intended!
type, public, abstract :: image
! Common components to all extensions
logical :: initialized = .false.
character(256) :: path = "" ! Path to image
integer :: dimensions(3) = -1 ! Dimensions of image
contains
procedure :: initialize
! Abstract interface pxvalues_image specified what the interface must
! look like. Deferred attribute means that extensions of image
! must specify a specific procedure for the pxvalues binding. All
! specific procedures must have the same interface bar the passed
! argument.
procedure(pxvalues_image), deferred :: pxvalues
procedure :: getMeta
end type image
abstract interface
subroutine pxvalues_image(obj, ...)
import :: image
class(image), intent(in) :: obj
...
end subroutine pxvalues_image
end interface
! A type for images that have integer2 data.
type, public, extends(image) :: image_integer2
contains
procedure :: pxvalues => pxvalues_integer2
end type image_integer2
! A type for images that have integer4 data.
type, public, extends(image) :: image_integer4
contains
procedure :: pxvalues => pxvalues_integer4
end type image_integer4
The specific procedures ''pxvalues_integer2'', ''pxvalues_integer4'', etc, then take an initial argument that is of the extension type.
Rather than setting the datatype component, the code that creates the initial "image" object should instead then create the object as the appropriate extension of image, perhaps:
subroutine create_image(object)
class(image), intent(out), allocatable :: object
...
! We want an image that for integer2's
allocate(image_integer2 :: object)
There are implication of this approach that require more knowledge of your code than can be given in isolated example snippets.
回答2:
How about having an actual procedure pxvalues
like this:
subroutine pxvalues(this)
select case (this%datatype)
case (0)
call this%pxvalues_integer
case (1)
call this%pxvalues_real
end select
end subroutine
回答3:
If pxvalues is a module procedure defined with an interface, you could do the following:
interface pxvalues ; module procedure &
pxvalues_integer , &
pxvalues_real
end interface
来源:https://stackoverflow.com/questions/11539050/how-to-specify-procedures-to-be-executed-depending-on-data-type-of-variable